我真的希望这是一个简单的例子,让我错过了解复杂的Python2导入机制。我有以下设置:
$> ls -ltr pypackage1
total 3
-rw-r--r-- 1 pelson pelson 0 Aug 17 19:20 io.py
-rw-r--r-- 1 pelson pelson 0 Aug 17 19:20 __init__.py
-rw-r--r-- 1 pelson pelson 57 Aug 17 19:22 code.py
$> cat pypackage1/code.py
from __future__ import absolute_import
import zipfile
即。我只有一个包含空__init__.py
和io.py
以及2行code.py
文件的存根包。
我可以导入pypackage1
:
$> python -c "import pypackage1.code"
但是我无法运行code.py
文件:
$> python pypackage1/code.py
Traceback (most recent call last):
File "pypackage1/code.py", line 3, in <module>
import zipfile
File "python2.7/zipfile.py", line 462, in <module>
class ZipExtFile(io.BufferedIOBase):
AttributeError: 'module' object has no attribute 'BufferedIOBase'
显然问题与zipfile
模块在内置io
模块上获取我的相对io模块有关,但我认为我的from __future__ import absolute_import
会修复它。
提前感谢您的帮助,
答案 0 :(得分:7)
这是正确的行为。如果你想修复错误,只需不要从包内运行。
当您运行包内的脚本时,python不会将该目录解释为包,因此将工作目录添加到PYTHONPATH
。
这就是为什么io
模块导入的zipfile
模块是您的io
模块而不是标准库中的模块。
我建议您在包外(或bin/scripts
文件夹)创建一个简单的启动器脚本,然后启动它。此脚本可以包含以下内容:
from pypackage1 import code
code.main()
另一种方法是告诉python解释器您要执行的文件是模块的一部分。您可以使用-m
命令行选项执行此操作。在你的情况下你必须这样做:
python -m pypackage1.code
请注意,-m
的参数应为模块名称,而不是文件名。
答案 1 :(得分:2)
一种解决方案是将from __future__ import absolute_import
置于zipfile.py
模块中。虽然您的模块使用绝对导入,但 zipfile 模块不是。
另一个选择是不从包目录运行。您可能不应该从包目录中运行解释器。
答案 2 :(得分:1)
文件结构:
test.py
mylib/__init__.py
mylib/__collections.py
mylib/collections.py
mylib/mymod.py
此解决方案允许:
在test.py中:
from collections import deque
from mylib.collections import mydict
在mylib / __ init __。py:
from __future__ import absolute_import
from . import collections
from . import mymod
在mylib / __ collections.py中:
class MyDict (dict):
pass
在mylib / collections.py中:
from __collections import *
在mylib / mymod.py中:
from __future__ import absolute_import
from collections import deque
try:
# Module running as part of mylib
from .collections import MyDict
except ValueError:
# Module running independently
from __collections import MyDict
以上适用于Python&gt; = 2.5。 Python 3不需要来自__future__ import absolute_import'的行。