如何制作。导入实用程序`

2024-10-02 14:21:56 发布

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

我有以下目录结构:

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中,我有:

^{pr2}$

现在,在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变得很复杂,特别是因为我有python3.2,而且我不喜欢使用模块imp,因为它已经过时了。而且,这似乎只会变得更加复杂。在

我有什么遗漏吗?这一切看起来都很难看,而且对于一个并不罕见的用例来说太复杂了(对我来说)。我的黑客有更简洁的版本吗?在

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


Tags: pathpyimportpackagebaseosdiranother
2条回答

(注意,这个答案是通过将this answerthis question的信息拼凑而成的,所以如果你喜欢的话,就去投票吧)

这看起来不那么老套,至少在Python2.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"。通常,您的可执行文件位于包的根目录之上,然后可以简单地使用:

^{pr2}$

不用大惊小怪。在

或者,如果您想执行包中的脚本,您实际上将其作为包的一部分调用(同样,从包的父目录调用):

python -m some_tools_dir.other_utils

你能把顶端的根路径添加到PYTHONPATH中吗?在

如果是这样的话,您可以添加

__init__.py

文件到一些工具目录(和/或其他一些工具目录)

然后从另一个_实用工具.py你知道吗

^{pr2}$

在另一个-工具.py你知道吗

from some-tools-dir import other_utils

然后可以删除符号链接,并使用适当的名称空间。在

相关问题 更多 >