首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从项目根目录导入模块

从项目根目录导入模块
EN

Stack Overflow用户
提问于 2021-04-18 00:00:46
回答 1查看 87关注 0票数 2

我在GitHub上见过许多Python项目,它们使用非常漂亮和干净的导入,它们在项目的根目录中定义自己的类型,并从内部的子包中导入它们。

例如,您可以具有如下的目录结构:

代码语言:javascript
复制
project
    - foo
        - foo.py
    - bar
        - baz
            - baz.py
        - bar.py
    main.py
    types.py

types.py中可能有一些类是项目中的核心数据类型。

代码语言:javascript
复制
# types.py

from dataclasses import dataclass


@dataclass(frozen=True)
class ImportantType:
    """This is a core type within the project that's used by sub-packages."""
    foo: str
    bar: str

然后,有趣的是,在任何一个子包中,您都可以找到如下代码:

代码语言:javascript
复制
# foo/foo.py

from project import types

def example():
    f = types.ImportantType("foo", "bar")
    # does some processing on f.

据我所知,Python导入通常不是这样工作的。但是,能够将数据模型放在项目的根目录中,并且能够导入相对于项目根目录的包和模块,这似乎是非常干净的。

为了能够像这样使用导入,您如何设置您的项目?

thefuck就是一个使用它的项目的例子,这里有一个到the file importing from root的链接。

免责声明:我已经搜索了代码,他们没有向PYTHONPATH添加包,也没有使用sys.path方法。

EN

回答 1

Stack Overflow用户

发布于 2021-04-18 02:25:59

只有在不安装包的情况下才需要设置PYTHONPATH。在内部,Python搜索sys.path以查找您使用fromimport关键字指定的任何内容。路径在根目录停止,这些子目录告诉python它需要搜索特定的目录序列来找到正确的文件。

代码语言:javascript
复制
rootdir/
  project/
     __init__.py 
     foo/
        __init__.py # All __init__.py file can be empty
        hello_module.py
      tests/test_import.py
  setup.py

>>>> print(sys.path)
['', '/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python39.zip', '/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9', '/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/lib-dynload', '/usr/local/lib/python3.9/site-packages', '/usr/local/Cellar/protobuf/3.14.0/libexec/lib/python3.9/site-packages']

https://docs.python.org/3.5/library/sys.html#sys.path

代码语言:javascript
复制
#project/foo/hello_module.py
def example():
   return ("hello module")


#tests/test_import.py
import os, sys
import unittest

class TestStringMethods(unittest.TestCase):
    def test_import(self):
        try:
            from project.foo.hello_module import example
            self.assertEqual(example().lower(), 'hello module')
        except Exception:
            try:
                self.assertIsNone(os.environ["PYTHONPATH"], os.environ["PYTHONPATH"])
            except Exception:
                self.assertTrue(False, "Error PYTHONPATH not defined")
                pass
if __name__ == '__main__':
    unittest.main()

# setup.py
import setuptools
setuptools.setup(name='project',
  version='1.0',
  description='test import project',
  author='somebody not me',
  author_email='somebodynotme@example.net',
  packages=setuptools.find_packages(
    exclude=["test/"]
  )
 )

使用PYTHONPATH测试项目

代码语言:javascript
复制
PYTHONPATH=`pwd` python3 tests/tests_import.py
.
----------------------------------------------------------------------
Ran 1 test in 0.004s

OK

在未通过虚拟环境安装PYTHONPATH的情况下测试项目

代码语言:javascript
复制
## Setup venv
python3 -m venv venv
source venv/bin/activate

注意venv如何添加额外的路径

代码语言:javascript
复制
python3 -c "import sys; print(sys.path)"
['', '/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python39.zip', '/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9', '/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/lib-dynload', '/Users/somebodyotherthanme/stackoverflow/67140161/venv/lib/python3.9/site-packages']

安装测试包并运行它

代码语言:javascript
复制
pip install /path/to/rootdir
python3 tests/test_import.py

python3 tests/tests_import.py 
.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK

    (venv) ➜  root_dir/ ls venv/lib/python3.9/site-packages/project
__init__.py __pycache__ foo

Relative imports for the billionth time

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67140161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档