【问题标题】:AttributeError: 'module' object has no attribute (when using cPickle)AttributeError:“模块”对象没有属性(使用 cPickle 时)
【发布时间】:2010-07-29 14:03:06
【问题描述】:

我正在尝试使用 cPickle 在远程环境中加载该函数。但我得到了 错误“‘模块’对象没有属性……”。我真正卡住的地方是命名空间有 已经包含该属性,即使它无法加载 请帮忙

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'

【问题讨论】:

    标签: python


    【解决方案1】:

    我发现此链接很有帮助: http://stefaanlippens.net/python-pickling-and-dealing-with-attributeerror-module-object-has-no-attribute-thing.html

    它提供了两种解决方案。更好的解决方案是在加载模块的头部添加(或__main__):

    from myclassmodule import MyClass
    

    但我认为应该存在更好的解决方案。

    【讨论】:

      【解决方案2】:

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

      请注意,函数(内置和 用户定义的)被“充分 合格的”名称参考,而不是由 价值。这意味着只有 函数名称被腌制,以及 函数的模块名称 定义在。既不是函数的 代码,也不是它的任何功能 属性被腌制。就这样 定义模块必须是可导入的 unpickling 环境,以及 模块必须包含命名对象, 否则会引发异常。

      您在定义 fun1 的模块中删除了对 fun1 的引用,因此出现错误。

      【讨论】:

      • 我故意删除了引用,但是在 eval() 期间它再次在命名空间中重新创建
      • 如果不深入研究它,我会想象 eval 在 run 模块的全局范围内定义函数,而不是最初定义它的模块(可能是 __main__ ?)。更好的测试练习是在另一个模块(“my_funcs.py”)中定义函数,该模块维护对函数对象的引用。请记住,函数对象并没有真正腌制 - 只是完全限定的名称。定义它的模块必须是可导入的,并且必须具有函数名作为属性。
      • 你熟悉并行python吗?他们的做法完全相同,他们腌制 func 及其参数并发送到运行函数。但是当他们执行 run() 时,它会完美执行。我想知道他们是如何实现的,是不是联系parallel python比较好?
      • 不,我不熟悉它。不管他们是怎么做的(如果需要,请阅读他们的源代码),您都错过了关于酸洗功能的要点。函数对象本身未腌制。解析为函数对象的完全限定名称被腌制。对于您想要做的事情(在 unpickling 环境中动态定义函数),您需要创建一个可通过相同路径导入的模块(如果函数在 mylib.funcs 中定义,那么您需要能够导入 mylib .funcs) 并且该模块对象必须使用相同的 attr 名称引用函数对象。
      【解决方案3】:

      函数的模块名称保存在pickle中,当您执行loads时,它会在__main__或原来的任何地方寻找fun1

      【讨论】:

      • 那么 fun1 是如何集成到模块中的,比如说 run
      【解决方案4】:

      尝试添加

      from your_first_module import fun,fun1 
      

      进入run.py

      【讨论】:

        猜你喜欢
        • 2010-11-18
        • 2018-08-28
        相关资源
        最近更新 更多