在python中使用绝对导入和处理相对模块名冲突

2024-10-05 14:23:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我真的希望这是一个简单的例子,我错过了理解复杂的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和{},还有一个2行code.py文件。在

我可以导入pypackage1

^{pr2}$

但我无法运行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'

{{{cdio>很明显,这个模块的问题已经解决了。在

提前感谢您的帮助


Tags: 文件inpyioimportinitlinecode
3条回答

文件结构:

test.py
mylib/__init__.py
mylib/__collections.py
mylib/collections.py
mylib/mymod.py

此解决方案允许:

  • 在测试.py调用两个mylib.收藏在
  • 在mymod.py公司当它作为库的一部分运行时,以及当它独立运行时(例如对于测试代码),调用上面的方法

在测试.py公司名称:

^{pr2}$

在mylib/\uu init\uy.py中:

from __future__ import absolute_import
from . import collections
from . import mymod

在mylib中/__收藏.py公司名称:

class MyDict (dict):
    pass

在mylib中/收藏.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>;=2.5。Python3不需要“from优future_UuImportabsolute_import”行。在

一种解决方案是将from __future__ import absolute_import放入zipfile.py模块中。虽然您的模块正在使用绝对导入,但zipfile模块不是。在

另一个选择是不从包目录运行。您可能不应该从包目录中运行解释器。在

这是正确的行为。如果您想修复错误,请不要从包内部运行。在

当您运行包中的脚本时,python不会将该目录解释为一个包,从而将工作目录添加到PYTHONPATH。 这就是为什么zipfile模块导入的io模块是您的io模块,而不是标准库中的模块。在

我建议在包外(或在bin/scripts文件夹中)创建一个简单的启动程序脚本,并启动它。此脚本可以简单地包含以下内容:

from pypackage1 import code

code.main()

另一种方法是告诉python解释器要执行的文件是模块的一部分。您可以使用-m命令行选项执行此操作。在您的情况下,您必须:

^{pr2}$

注意,-m的参数应该是模块名,而不是文件名。在

相关问题 更多 >