Python 如何使…从…开始。导入utils的工作

Python 如何使…从…开始。导入utils的工作,python,python-3.x,python-import,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 现在,在另一个too

我有以下目录结构:

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
现在,在另一个tool.py中,我想做:

import basetools.other_utils
这是行不通的,因为Python不能将
basetools
识别为Python包。 因此,我添加了一个空的
basetools/\uuuu init\uuuu.py
。 现在,在
其他工具中,我得到了一个例外:

    import base_utils
ImportError: No module named base_utils
    from . import base_utils
ValueError: Attempted relative import in non-package
因此,我将该行更改为:

from . import base_utils
还有另一个工具.py现在可以工作了

但是,
sometool.py
不再工作。它导入了
其他工具
,在那里我得到了一个异常:

    import base_utils
ImportError: No module named base_utils
    from . import base_utils
ValueError: Attempted relative import in non-package
现在,我可以将此破解/解决方法添加到
一些工具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,如果这简化了任何事情。

您能够将顶部根路径添加到PYTHONPATH中吗

如果是,您可以添加

__init__.py
将文件放入某些工具目录(和/或某些其他工具目录)

那么从其他方面来看,你是这样做的

from some-tools-dir import base_utils
from some-tools-dir import other_utils
在另一个tool.py中,您可以

from some-tools-dir import base_utils
from some-tools-dir import other_utils
然后可以删除符号链接,并使用适当的名称空间

(请注意,这个答案是通过将和中的信息拼凑而成的,因此,如果您喜欢,请向上投票)

这看起来没有那么粗糙,至少可以与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实际上称之为。通常,可执行文件位于包的根目录之上,然后可以简单地使用:

from some_tools_dir import other_utils
没有任何麻烦

或者,如果要执行存在于包中的脚本,可以将其作为包的一部分调用(同样,从包的父目录调用):


我已经做到了。这就是我在问题中写的。另外,由于模块名不能包含“-”
”,因此代码无法工作。请注意,在我的问题中,我有意使用带“-”的目录名,因为我希望有一个通用的解决方案。您的解决方案假定它是一个有效的包名(
some\u tools\u dir
)然而,我决定重组我的文件并遵循Guidos的建议。另外,
python-m
不是一个真正的解决方案,因为我希望脚本能够执行,但我不知道如何通过hashbang实现这一点。