Python 货架:可以';t pickle<;类别';方法'>;:属性查找内置项。方法失败

Python 货架:可以';t pickle<;类别';方法'>;:属性查找内置项。方法失败,python,python-3.x,pickle,shelve,Python,Python 3.x,Pickle,Shelve,我正在使用shelve存储一些数据 Traceback (most recent call last): File "rogue.py", line 312, in <module> curses.wrapper(game) File "/usr/lib/python3.3/curses/__init__.py", line 94, in wrapper return func(stdscr, *args, **kwds) File "rogue.py", l

我正在使用shelve存储一些数据

Traceback (most recent call last):
    File "rogue.py", line 312, in <module>
    curses.wrapper(game)
File "/usr/lib/python3.3/curses/__init__.py", line 94, in wrapper
    return func(stdscr, *args, **kwds)
File "rogue.py", line 289, in game
    save_game(y,x)
File "rogue.py", line 119, in save_game
    file['player'] = player
File "/usr/lib/python3.3/shelve.py", line 124, in __setitem__
    p.dump(value)

_pickle.PicklingError: Can't pickle <class 'method'>: attribute lookup builtins.method failed
玩家是类实体:

player = entity(y,x, '@', 200, False)
class entity:
def __init__(self, y, x, ch, speed, ai=True):
    self.y = y
    self.x = x
    self.ch = ch
    self.speed = speed
    self.ai = ai


    self.ap = 0
    self.current_action = {'action': self.wait, 'cost': self.speed}
    self.my_turn = False

def draw(self):
    world[self.y][self.x].walkable = False
    gamepad.addch(self.y, self.x, self.ch)

def take_turn(self):

    self.my_turn = True
    cost = self.current_action['cost']
    self.current_action['action']()

    return cost
def move(self, dy, dx):

    if self.my_turn == False:
        self.current_action = {'action': partial(self.move, dy,dx), 'cost':200}
        deck.append(self)

    if self.my_turn == True:

        #p = previous
        py = self.y
        px = self.x


        pt = world[py][px]
        #Paint previous ground tile
        pt.walkable = True
        gamepad.addch(pt.y,pt.x,pt.ch)

        if world[dy][dx].walkable == True:
            self.y = dy
            self.x = dx
            world[dy][dx].walkable = False

        if self.ai == False:
            draw_map(self.y,self.x)


        self.my_turn = False
    return self.y,self.x

def wait(self):
    self.current_action = {'action': self.wait, 'cost': self.speed}
def drunk_move(self):
    dy = self.y + random.randint(-1,1)
    dx = self.x + random.randint(-1,1)
    self.move(dy, dx)
def ai_simple(self):

    #Figure out if player is higher or not:
    wherey = self.y - player.y
    if wherey > 0:
        dy = self.y-1
    else:
        dy = self.y+1

    wherex = self.x - player.x
    if wherex > 0:
        dx = self.x-1
    else:
        dx = self.x+1

    self.move(dy, dx)
这是类实体的代码:

player = entity(y,x, '@', 200, False)
class entity:
def __init__(self, y, x, ch, speed, ai=True):
    self.y = y
    self.x = x
    self.ch = ch
    self.speed = speed
    self.ai = ai


    self.ap = 0
    self.current_action = {'action': self.wait, 'cost': self.speed}
    self.my_turn = False

def draw(self):
    world[self.y][self.x].walkable = False
    gamepad.addch(self.y, self.x, self.ch)

def take_turn(self):

    self.my_turn = True
    cost = self.current_action['cost']
    self.current_action['action']()

    return cost
def move(self, dy, dx):

    if self.my_turn == False:
        self.current_action = {'action': partial(self.move, dy,dx), 'cost':200}
        deck.append(self)

    if self.my_turn == True:

        #p = previous
        py = self.y
        px = self.x


        pt = world[py][px]
        #Paint previous ground tile
        pt.walkable = True
        gamepad.addch(pt.y,pt.x,pt.ch)

        if world[dy][dx].walkable == True:
            self.y = dy
            self.x = dx
            world[dy][dx].walkable = False

        if self.ai == False:
            draw_map(self.y,self.x)


        self.my_turn = False
    return self.y,self.x

def wait(self):
    self.current_action = {'action': self.wait, 'cost': self.speed}
def drunk_move(self):
    dy = self.y + random.randint(-1,1)
    dx = self.x + random.randint(-1,1)
    self.move(dy, dx)
def ai_simple(self):

    #Figure out if player is higher or not:
    wherey = self.y - player.y
    if wherey > 0:
        dy = self.y-1
    else:
        dy = self.y+1

    wherex = self.x - player.x
    if wherex > 0:
        dx = self.x-1
    else:
        dx = self.x+1

    self.move(dy, dx)

在发布这篇文章之前,我试着用pudb做最后一次检查——我也发现了一个错误

file['world'] = world
_

这是类平铺:

class tile:
def __init__(self,y,x,walkable,ch):
    self.x = x
    self.y = y
    self.walkable = walkable
    self.ch = ch
最后,这是调用shelve的完整函数:

def save_game():
    file = shelve.open('savegame', 'n')
    file['world'] = world
    file['player']= player

    file.close()
我相信这就是所有相关的代码


导致这些错误的原因是什么?

第一个问题是由实体类中的这一行引起的:

self.current_action = {'action': self.wait, 'cost': self.speed}
current_action
包含对绑定方法的引用,这些方法不能被pickle。您可以使用并确实更改pickle行为,以便在pickle时不pickle方法,而是pickle方法的名称(或者在已分配
部分
对象的情况下,名称和参数),并在取消pickle时恢复该值

我不太确定您的第二个问题,但如果它只在调试器内部运行时发生,则可能是调试器如何加载
\uuuu主模块的问题。您可以尝试将
\uuuuu main\uuuu
块移动到另一个模块中,然后从那里导入和隐藏代码。有时,这可以解决像这样的问题

self.current_action = {'action': self.wait, 'cost': self.speed}