如何制作`来自。 import utils` work

时间:2014-07-18 13:18:54

标签: python python-3.x python-import

我有以下目录结构:

some-tools-dir/
    base_utils.py
    other_utils.py
    some-tool.py
    some-other-tool.py

some-other-tools-dir/
    basetools -> symlink to ../some-tools-dir
    yet-another-tool.py

other_utils.py中,我有:

import base_utils

现在,在yet-another-tool.py,我想这样做:

import basetools.other_utils

这不起作用,因为Python不会将basetools识别为Python包。 所以我添加一个空的basetools/__init__.py。 现在,在other_utils中,我得到了例外:

    import base_utils
ImportError: No module named base_utils

所以我将该行更改为:

from . import base_utils

而且yet-another-tool.py现在有效。

但是,some-tool.py不再有效。它导入other_utils,然后我得到例外:

    from . import base_utils
ValueError: Attempted relative import in non-package

现在,我可以将此黑客/解决方法添加到some-tools-dir/*-tool.py

import os, sys
__package__ = os.path.basename(os.path.dirname(os.path.abspath(__file__)))
sys.path += [os.path.dirname(os.path.dirname(os.path.abspath(__file__)))]
__import__(__package__)

此外,将所有本地导入相对于这些文件。

我猜这解决了这个问题。但是,它看起来有点非常难看,我必须修改sys.path。我尝试了这种黑客的几种变体,但是,如果可能的话,我想支持多个Python版本,因此使用模块importlib变得复杂,尤其是。因为我有Python 3.2,我不喜欢使用模块imp,因为它已被弃用。而且,它似乎变得更加复杂。

有什么我想念的吗?对于一个似乎并不太常见的用例来说,这一切看起来都很丑陋而且太复杂了(对我来说)。我的黑客有更清洁/更简单的版本吗?

我愿意做的限制是只支持Python> = 3.2,如果这简化了任何事情。

2 个答案:

答案 0 :(得分:1)

(请注意,此答案是通过拼凑来自this answerthis question的信息构建的,因此如果您愿意,可以将其投票给他们。

这看起来不那么黑,至少可以使用Python 2.7 +:

if __name__ == "__main__" and __package__ is None:
    import sys, os.path as path
    sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

from some_tools_dir import other_utils

我认为你发现这个困难的主要原因是因为在python包中包含可执行脚本实际上并不常见。 Guido van Rossum实际上称之为"antipattern"。通常,您的可执行文件位于包的根目录之上,然后只需使用:

from some_tools_dir import other_utils

没有任何大惊小怪。

或者,如果你想执行一个包含在包中的脚本,你实际上将它称为包的一部分(再次,从包的父目录):

python -m some_tools_dir.other_utils

答案 1 :(得分:0)

您是否可以将最高根路径添加到PYTHONPATH?

如果是,您可以添加

__init__.py

将文件存入some-tools-dir(和/或其他工具-dir)

然后从other_utils.py开始

from some-tools-dir import base_utils

在yet-another-tool.py中你做了

from some-tools-dir import other_utils

然后,您可以删除符号链接,并具有正确的命名空间。