Skip to main content
 首页 » 编程设计

python之搁置:无法 pickle class 'method' >:属性查找 builtins.method 失败

2025年05月04日26wuhuacong

我正在使用 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 

我环顾四周,发现有关未绑定(bind)方法的内容可能会导致此问题,但我无法在我的代码中找到问题。

问题出现在

file['player'] = player 

玩家是类实体:

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 

_

│  File "/usr/lib/python3.3/shelve.py", line 124, in                    │ 
│__setitem__                                                            │ 
│    p.dump(value)                                                      │          
│_pickle.PicklingError: Can't pickle <class                             │ 
│'__main__.tile'>: attribute lookup __main__.tile failed                │ 

(在没有 pudb 的情况下运行代码时不显示)

这就是世界:

world = [[ tile(yy,xx,True,'.') 
    for xx in range(WORLD_WIDTH) ] 
        for yy in range(WORLD_HEIGHT) ] 

这是类磁贴:

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 的绑定(bind)方法的引用。你可以使用 __getstate__和 __setstate__改变你的 pickle 行为,所以你不 pickle 方法,但它的名称(或在分配 partial 对象的情况下的名称和参数)在 pickle 时,并在 unpickling 时间恢复该值。

我不太确定你的第二个问题,但如果它只发生在你在调试器中运行它时,它可能是调试器如何加载 __main__ 模块的问题。您可以尝试将您的 __main__ block 移动到另一个模块并从那里导入和启动您的代码。有时这可以解决这些问题。