根据这里的建议,我的包(或包含我的模块的目录)位于c:/python34/lib/site packages。目录包含一个__init__.py,sys.path包含目录的路径,如图所示。
但我仍然收到以下错误:
1 2 3 4 5 6 7 8 9 10
| Traceback (most recent call last):
File"C:/Python34/Lib/site-packages/toolkit/window.py", line 6, in <module>
from catalogmaker import Catalog
File"C:\Python34\Lib\site-packages\toolkit\catalogmaker.py", line 1, in <module>
from patronmaker import Patron
File"C:\Python34\Lib\site-packages\toolkit\patronmaker.py", line 4, in <module>
class Patron:
File"C:\Python34\Lib\site-packages\toolkit\patronmaker.py", line 11, in Patron
patrons = pickle.load(f)
ImportError: No module named 'Patron' |
我有一个名为"provider"的provider.py类,但没有名为provider的模块,所以我不确定错误消息中的最后一条语句是什么意思。我非常感谢你对我所缺少的东西的看法。
在Windows32位计算机上运行python版本3.4.1。
- 发布你的代码!
- 你在吃什么?什么时候/怎么腌制的?你可能会遇到这样的问题。
- 我有4个模块,每个模块包含若干行代码和pickle文件,它们都在一起交互。张贴这些是最佳的吗?思想?
- 使用pickle进行数据持久性保存2个字典和L列表。
- 在异常之前在一行上尝试pprinting pythons sys.path并验证任何引用的路径是否与某个sys路径相关?在黑暗中拍摄。
- @布伦巴恩的好建议。然而,你指出的泡菜问题可能不会在这里发挥作用。我删除了所有的pickle文件,程序仍然返回相同的错误,除了回溯中的最后一行,它现在是:AttributeError: Can't get attribute 'Patron' on 。所以我似乎不再有重要的错误,而是属性错误。
- 您的代码是如何运行的?请记住,运行脚本时,其模块名将是__main__,而不是常规名称,这样可能会中断pickle的导入尝试。你是直接运行patomaker.py吗?
- @ThorSummoner我在这里阅读了关于pprint的文档,但我不知道它在这里是如何应用的,也不知道如何实现它。
- @布伦巴恩,我用的是魔咒。我的一个模块window.py有if __name__ =="__main__": app = Gui()。gui是window.py中唯一的类。我做得对吗?
- 明天我会收到你的反馈。现在是凌晨2:08。同时,谢谢大家!
- @布伦巴恩:我想你可能是对的。在没有看到代码的情况下,很难知道如何解决这个问题。@塞德,如果你想用dill而不是pickle,这可以解决你的问题。pickle通过引用序列化类,但在许多对象中不能很好地使用__main__。在dill中,不需要参照序列化classes,可以更好地处理__main__的问题。在这里获取dill:github.com/uqfoundation
- 好啊。我刚把模块推到Github回购这里。我以前是window.py。我希望这有帮助。
- @sedeh我建议将pprint用作调试工具,以便更容易地读取sys.path输出。
- @雷神召唤师好,我在导入模块之前插入了from pprint import pprint pprint(vars())。这里有输出。不知道该怎么办。在同一地点使用import pdb pdb.set_trace()产生C:\Python34\python.exe C:/Python34/Lib/site-packages/toolkit/window.py > c:\python34\lib\site-packages\toolkit\window.py(8)() -> from catalogmaker import * (Pdb)。
- 这里是window.py中更完整的pdb步骤。ideone.com/yryrdf网站
- @sedeh噢,我对你的vars不感兴趣,我对sys.path import sys; pprint(sys.path)感兴趣,我不确定我是否真的能提供很多帮助,即使你提供了这样的信息;我只想你应该在那个路径中看到模块的包含文件夹,知道它不是路径问题。
- 您应该显示是什么导致了回溯,而不仅仅是回溯。
您正在将所有用户实例(即self保存到Patron类属性Patron.patrons中。然后,您将尝试从类内pickle类属性。这会使pickle窒息,但我相信dill应该能够处理。是否确实需要将所有类实例保存到用户列表中?做这件事有点奇怪…
pickle通过引用序列化类,但对于许多对象来说,它不能很好地与__main__配合使用。在dill中,不必通过引用序列化类,它可以处理__main__的问题,效果更好。获取dill网址:https://github.com/uqfoundation
编辑:我试过你的代码(只做了一个小改动),它起作用了。
1
| dude@hilbert>$ python patronmaker.py |
然后启动python…
1 2 3 4 5
| >>> import dill
>>> f = open('patrons.pkl', 'rb')
>>> p = dill.load(f)
>>> p
[Julius Caeser, Kunte Kinta, Norton Henrich, Mother Teresa] |
我所做的唯一改变是取消对patronmaker.py末尾的行的注释,这样就节省了一些用户……我也用各地的import dill as pickle取代了import pickle。
所以,即使通过下载和运行您的代码,我也不能在dill中产生错误。我使用的是Github最新的dill。
附加编辑:你上面的回溯来自一个ImportError。您安装模块了吗?如果您没有使用setup.py来安装它,或者您的PYTHONPATH上没有您的模块,那么无论您如何序列化,都不会找到您的模块。
更多编辑:看看你的代码,你应该为patrons使用singleton模式……它不应该在class Patron中。类级别的代码块用于将用户加载到Patron.patrons中,这肯定会导致问题……而且可能是某种形式的错误的来源。我还看到你在从patrons类中删除属性Patrons.patrons(甚至不是类本身),这太疯狂了,不要这样做。另外请注意,当您试图获得用户时,您使用Patron.patrons…这是调用类对象而不是实例。将赞助人移出班级,并直接使用单例作为赞助人列表。另外,您通常应该使用赞助人实例,因此,如果您想让每个赞助人知道其他所有赞助人是谁,p = Patron('Joe', 'Blow'),那么p.patrons,以获得所有赞助人……但您需要编写一个Patrons.load方法,读取单例赞助人列表……您还可以使用property使load给出y你看起来像个属性。
如果你建立了一个单一的顾客(作为一个名单)或"注册"的顾客(作为一个口述),如果你喜欢,然后检查是否有一个顾客腌菜文件存在…加载到注册表…不要从内部的顾客类做…事情应该好多了。您的代码当前正试图在类定义构建类对象时加载类实例。那太糟糕了…
另外,不要期望人们去下载你的代码并为你调试它,当你没有提供一个最小的测试用例或者没有足够的信息来说明如何创建回溯时。你可能在dill中发现了一个有效的酸洗错误,因为有些黑角箱子,但我不能告诉B/C我不能复制你的错误。但是,我可以告诉您需要一些重构。
只是要明确一点:
将您的用户从用户初始化mess移到新文件patrons.py中。
1 2 3 4 5 6 7 8
| import os
import dill as pickle
#Initialize patrons with saved pickle data
if os.path.isfile('patrons.pkl'):
with open("patrons.pkl", 'rb') as f:
patrons = pickle.load(f)
else: patrons = [] |
然后在patronmaker.py和其他任何地方你都需要单身汉…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import dill as pickle
import os.path
import patrons as the
class Patron:
def __init__(self, lname, fname):
self.lname = lname.title()
self.fname = fname.title()
self.terrCheckedOutHistory = {}
#Add any created Patron to patrons list
the.patrons.append(self)
#Preserve this person via pickle
with open('patrons.pkl', 'wb') as f:
pickle.dump(the.patrons, f) |
而且,您应该很好,除非您的代码遇到了这样一种情况:模块上的属性由于动态添加而无法序列化(参见https://github.com/uqfoundation/dill/pull/47),这肯定会使pickle失败,在某些情况下,dill也会失败……可能是因为模块上有AtrributeError。我就是不能复制这个…我已经完成了。
- 你说得很对,谢谢你指出了问题所在。在进入DILL之前,让我尝试在这里实现解决方案:stackoverflow.com/questions/7928450/namespace on python pick&zwnj;&8203;le。你的解释和那篇文章中穆拉德的解释完美地抓住了我的问题。
- 即使使用DILL,错误仍然存在。调用dill上的dump可以正常工作,但调用所选数据上的load仍会引发错误:AttributeError: Can't get attribute 'Patron' on &zwnj;&8203;。
- 我刚下载了你的代码,我试过的都成功了。我在Mac上使用的是python 3.4.1。
- 感谢迈克提供的教学要点!很抱歉到处跑。下次我会做得更好。
- 你应该把你给我发的邮件发出去。当我看到你的完整回溯,以及是什么触发了它时,它告诉我你很可能遇到了我在指向dillgithub页面的链接中提到的问题。这是一个对动态编辑的模块进行修改的小例子……你看到的AttributeError的原因是什么。您需要进行一些重构——我再次建议您构建一些存储您的不在赞助人类中的赞助人实例列表的东西。上面您喜欢的堆栈溢出问题的答案适用于这里。
- 要清楚,您应该重构,这样dump和load都是由同一个文件完成的,并且无论您如何运行代码(从window.py或从patronmaker.py或从解释器)。
- 我进行了重构,使dump和load由同一个文件完成。我使用了全局变量,以便dump和load函数可以访问相同的列表。它奏效了!我用过泡菜,但我相信迪尔也能处理这项任务。感谢Mike提供的有用反馈。