AttributeError:'module'对象没有属性(使用cPickle时)

17 投票
4 回答
44036 浏览
提问于 2025-04-16 02:01

我正在尝试在一个远程环境中使用cPickle加载一个函数。但是我遇到了一个错误,提示“这个'module'对象没有属性...”。我现在卡住的地方是,命名空间中已经包含了那个属性,尽管它加载失败了。请帮帮我。

import inspect
import cPickle as pickle
from run import run


def get_source(func): 
 sourcelines = inspect.getsourcelines(func)[0]
 sourcelines[0] = sourcelines[0].lstrip()
 return "".join(sourcelines)

def fun(f):
 return f()

def fun1():
 return 10 

funcs = (fun, fun1) 

sources = [get_source(func) for func in funcs]

funcs_serialized = pickle.dumps((fun.func_name,sources),0)

args_serialized = pickle.dumps(fun1,0) 

#Creating the Environment where fun & fun1 doesnot exist 
del globals()['fun']
del globals()['fun1']

r = run() 

r.work(funcs_serialized,args_serialized) 

这是run.py

import cPickle as pickle

class run():
 def __init__(self):
  pass

 def work(self,funcs_serialized,args_serialized):

  func, fsources = pickle.loads(funcs_serialized)

  fobjs = [compile(fsource, '<string>', 'exec') for fsource in fsources]

    #After eval fun and fun1 should be there in globals/locals
  for fobj in fobjs:
   try: 
    eval(fobj)
    globals().update(locals())
   except:
    pass

  print "Fun1 in Globals: ",globals()['fun1']   
  print "Fun1 in locals: ",locals()['fun1']   
  arg = pickle.loads(args_serialized)

错误信息是

Fun1 in Globals:  <function fun1 at 0xb7dae6f4>
Fun1 in locals:  <function fun1 at 0xb7dae6f4>
Traceback (most recent call last):
  File "fun.py", line 32, in <module>
    r.work(funcs_serialized,args_serialized) 
  File "/home/guest/kathi/python/workspace/run.py", line 23, in work
    arg = pickle.loads(args_serialized)
AttributeError: 'module' object has no attribute 'fun1'

4 个回答

1

这个函数的模块名称会被保存到一个叫做pickle的文件里。当你使用loads这个功能时,它会去__main__或者最初保存这个函数的地方找fun1

9

来自 http://docs.python.org/library/pickle.html#what-can-be-pickled-and-unpickled 的内容:

要注意,函数(无论是内置的还是自己定义的)在被“序列化”(也就是保存)时,是通过“完全限定”的名字来引用的,而不是通过它的值。这意味着在保存时,只会保存函数的名字,以及它所在模块的名字。函数的代码和任何属性都不会被保存。因此,在反序列化(也就是读取)时,定义这个函数的模块必须是可以导入的,并且这个模块里必须包含这个名字的对象,否则就会出现错误。

你删除了定义 fun1 的模块中的 fun1 的引用,所以就出现了错误。

13

我发现这个链接很有帮助:

http://stefaanlippens.net/python-pickling-and-dealing-with-attributeerror-module-object-has-no-attribute-thing.html

这个链接提供了两个解决方案。更好的解决方案是在加载模块的开头(或者说__main__部分)添加一些内容:

from myclassmodule import MyClass

不过我觉得应该还有更好的解决办法。

撰写回答