【问题标题】:How to import without using sys.path?如何在不使用 sys.path 的情况下导入?
【发布时间】:2020-10-19 04:13:55
【问题描述】:

我有一个这样组织的 python3 项目:

project
    src
        __init.py__
        file1.py (contains Class1)
        file2.py (contains Class2)
    test
        test1.py (contains TestClass1)
        test2.py (contains TestClass2)

我希望能够将类从file1.py 导入file2.py,并从file1.pyfile2.py 导入test1.pytest2.py。在不设置 sys.path 的情况下完成此任务的最直接方法是什么?

我正在使用 python 3.7。

代码被称为:

cd project/src/ && python3 file2.py

作为:

cd project/ && python3 -m unittest discover

这是一个开源项目,因此欢迎任何想要的人访问我们的 GitHub 存储库的 URL,但我认为它与问题无关。

这应该不难,但它让我很适应。我已经阅读了Python3 import chapter 并搜索了规范的 Python 项目组织,但无济于事。

【问题讨论】:

  • 您是否有不想使用sys.path 的特殊原因?可以在运行测试之前设置PYTHONPATH 环境变量吗?
  • 这是一个合理的问题。对我来说, sys.path 似乎是一个 hack。我很难相信在一个简单的项目中没有更直接的方法来完成任务。其他语言,无论是比 Python 旧的还是新的,在这方面都没有困难。
  • 这个项目结构看起来很奇怪。像这样的设置意味着包本身被称为src——通常,src 是一个包含包的普通目录。为什么直接执行src/file2.py 时会有src/__init__.py?一个包意味着file2.py 作为包的一部分被执行,例如python3 -m package.src.file2。哪些部分包,哪些只是目录?
  • 您的链接很有帮助,@MisterMiyagi - 谢谢! “-m”标志确实是秘诀。我现在有一些工作。我会在回答我自己的问题时记录我得到的信息。

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


【解决方案1】:

这就是我最终得到的结果,这要感谢这里的建议和 Alex Martelli 的建议。秘诀是使用 Python 的 -m 标志。

project
    src
        __init.py__
        file1.py
            class Class1:
                pass
        file2.py
            from src.file1 import Class1
            class Class2:
                pass
            if __name__ == "__main__":
                # Instantiate Class2 here…
                pass
    test
        __init.py__
        test1.py
            from src.file1 import Class1
            class TestClass1:
                pass
        test2.py
            from src.file2 import Class2
            class TestClass2:
                pass

应用被调用为cd project && python3 -m src.file2

测试以cd project && python3 -m unittest 运行

【讨论】:

    【解决方案2】:

    使用__init__.py

    Python 使用 __init__.py 文件的存在来确定哪些目录是 Python 包。如果您像这样在项目中添加这些:

    project
        __init__.py
        src
            __init__.py
            file1.py (contains Class1)
            file2.py (contains Class2)
        test
            __init__.py
            test1.py (contains TestClass1)
            test2.py (contains TestClass2)
    

    您应该能够通过导入路径从测试中导入源代码:from project.src.file1 import Class1

    然后运行您的测试:python -m unittest discover -s /path/to/project/test

    使用setuptools

    您可以使用setuptools 来安装您的源代码,然后运行如下代码:

    cd project/ && python3 -m pip install . && python3 -m unittest discover
    

    您只需将setup.py 文件添加到项目的根目录。对于一个简单的setup.py 脚本,您可能需要参考https://github.com/google/mobly/blob/master/setup.py(我曾经使用过很多的项目)。有很多项目使用 setuptools,但其中许多项目的设置非常复杂,而且通常很难确切地看到发生了什么。

    【讨论】:

    • 感谢您的建议。我不知道 setuptools。对于这样一个简单的项目来说,这似乎有点矫枉过正。附加到 sys.path 的工作量更少,这仍然是我希望避免的事情!
    • 没有问题!不幸的是,除了这三个解决方案之外,我认为您不会找到一种更简单的方法来在给定的包树之外导入 python 代码。您还可以考虑将 __init__.py 放在 repo 的根目录中并相应地命名您的目录,但这可能需要更大的重构。
    • 谢谢,@kingkupps。如果有帮助,我很乐意在根目录中添加一个 init.py !如果我这样做,你能告诉我我会使用的导入语法吗?
    • 刚刚更新了我的答案!如果您使用该路线,您可能需要重命名您的一些项目树
    • 啊哈!如果我调用cd project/.. && python3 -m project.src.file2,它将起作用我的替代方案也需要python3 -m
    猜你喜欢
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    • 2020-08-06
    • 2020-10-11
    • 2021-12-05
    • 2019-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多