我试着通读关于兄弟姐妹导入的问题,甚至 软件包文档,但我还没找到答案。

结构如下:

├── LICENSE.md
├── README.md
├── api
│   ├── __init__.py
│   ├── api.py
│   └── api_key.py
├── examples
│   ├── __init__.py
│   ├── example_one.py
│   └── example_two.py
└── tests
│   ├── __init__.py
│   └── test_one.py

示例和测试目录中的脚本如何从 API模块和从命令行运行?

另外,我希望避免对每个文件都使用难看的sys.path.insert。肯定 这可以在Python中完成,对吧?


当前回答

项目

1.1用户

1.1.1 about.py

1.1.2 init.py

1.2技术

1.2.1 info.py

1.1.2 init.py

现在,如果你想访问User包中的about.py模块,从Tech包中的info.py模块,那么你必须将cmd(在windows中)路径带到项目中,即。 **C:\Users\Personal\Desktop\Project>**根据上面的包示例。你必须从这个路径输入python -m Package_name.module_name 例如,对于上面的包,我们必须做,

c:\用户\个人\桌面\项目>python -m Tech.info

小鬼点

不要在info模块后使用.py扩展名,即python -m Tech.info.py 输入this,其中兄弟包位于同一级别。 -m是标志,要检查它,你可以从CMD python——help

其他回答

存在的问题:

你只是不能让import mypackage在test.py中工作。你将需要一个可编辑的安装,改变到路径,或改变__name__和路径

demo
├── dev
│   └── test.py
└── src
    └── mypackage
        ├── __init__.py
        └── module_of_mypackage.py

--------------------------------------------------------------
ValueError: attempted relative import beyond top-level package

解决方案:

import sys; sys.path += [sys.path[0][:-3]+"src"]

在尝试在test.py中导入之前,请将上述内容放在上面。这是它。你现在可以导入mypackage了。

这在Windows和Linux上都可以工作。它也不会关心从哪个路径运行脚本。它足够短,可以拍打任何你需要它的地方。

为什么有效:

The sys.path contains the places, in order, where to look for packages when attempting imports if they are not found in installed site packages. When you run test.py the first item in sys.path will be something like /mnt/c/Users/username/Desktop/demo/dev i.e.: where you ran your file. The oneliner will simply add the sibling folder to path and everything works. You will not have to worry about Windows vs Linux file paths since we are only editing the last folder name and nothing else. If you project structure is already set in stone for your repository we can also reasonably just use the magic number 3 to slice away dev and substitute src

对于主要问题:

调用兄弟文件夹作为模块:

从. .进口siblingfolder

从兄弟文件夹调用a_file.py作为模块:

从. .兄弟文件夹导入a_file

在兄弟文件夹中的文件中调用a_function作为模块:

从. . siblingmodule。A_file import func_name_exists_in_a_file

最简单的方法。

进入lib/site-packages文件夹。

如果存在“easy_install.pth”文件,只需编辑它并添加您有脚本的目录,将其作为模块。

如果不存在,就把它变成一个…把你想要的文件夹放在那里

添加之后…, python会自动将该文件夹视为类似site-packages的文件夹,您可以将该文件夹或子文件夹中的每个脚本作为模块调用。

这是我用手机写的,很难设置成让每个人都能舒服地阅读。

厌倦了系统。路径黑客吗?

有很多可用的sys.path.append -hacks,但我发现了另一种解决问题的方法。

总结

将代码打包到一个文件夹中(例如packaged_stuff) 创建setup.py脚本,其中使用setuptools.setup()。(参见下面的minimal setup.py) 使用Pip install -e <myproject_folder>将包安装到可编辑状态 从packaged_stuff导入using。Modulename import function_name


设置

起点是您提供的文件结构,包装在名为myproject的文件夹中。

.
└── myproject
    ├── api
    │   ├── api_key.py
    │   ├── api.py
    │   └── __init__.py
    ├── examples
    │   ├── example_one.py
    │   ├── example_two.py
    │   └── __init__.py
    ├── LICENCE.md
    ├── README.md
    └── tests
        ├── __init__.py
        └── test_one.py

我会打电话给。在我的例子中,它位于C:\tmp\test_imports\。

api.py

作为测试用例,让我们使用下面的./api/api.py

def function_from_api():
    return 'I am the return value from api.api!'

test_one.py

from api.api import function_from_api

def test_function():
    print(function_from_api())

if __name__ == '__main__':
    test_function()

尝试运行test_one:

PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
  File ".\myproject\tests\test_one.py", line 1, in <module>
    from api.api import function_from_api
ModuleNotFoundError: No module named 'api'

尝试相对导入也不会起作用:

使用from ..api。API导入函数from_api的结果为

PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
  File ".\tests\test_one.py", line 1, in <module>
    from ..api.api import function_from_api
ValueError: attempted relative import beyond top-level package

步骤

创建一个setup.py文件到根目录


setup.py的内容是*

from setuptools import setup, find_packages

setup(name='myproject', version='1.0', packages=find_packages())

使用虚拟环境


如果您熟悉虚拟环境,请激活一个,然后跳转到下一步。使用虚拟环境并不是绝对必需的,但从长远来看,它们确实会帮助你(当你有多个正在进行的项目时)。最基本的步骤是(在根文件夹中运行)

创建虚拟环境 Python -m venv venv 激活虚拟环境 ./venv/bin/activate (Linux, macOS)或./venv/Scripts/activate (Win)

要了解更多信息,请参考谷歌“python virtual env tutorial”或类似内容。除了创建、激活和取消激活之外,您可能永远不需要任何其他命令。

创建并激活虚拟环境后,控制台应该在括号中给出虚拟环境的名称

PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>

你的文件夹树应该看起来像这样**

.
├── myproject
│   ├── api
│   │   ├── api_key.py
│   │   ├── api.py
│   │   └── __init__.py
│   ├── examples
│   │   ├── example_one.py
│   │   ├── example_two.py
│   │   └── __init__.py
│   ├── LICENCE.md
│   ├── README.md
│   └── tests
│       ├── __init__.py
│       └── test_one.py
├── setup.py
└── venv
    ├── Include
    ├── Lib
    ├── pyvenv.cfg
    └── Scripts [87 entries exceeds filelimit, not opening dir]

PIP在可编辑状态下安装项目


使用pip安装你的顶级包myproject。诀窍是在进行安装时使用-e标志。通过这种方式,它被安装在可编辑状态下,对.py文件的所有编辑都将自动包含在已安装的包中。

在根目录下运行

PIP install -e。(注意这个点,它代表“当前目录”)

您还可以看到它是通过使用pip freeze安装的

(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
  Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0

添加。。导入文件中


注意,您必须添加myproject。只能输入到其他无法工作的输入中。没有setup.py和pip安装的导入仍然可以正常工作。请参见下面的示例。


测试解决方案

现在,让我们使用上面定义的api.py和下面定义的test_one.py测试解决方案。

test_one.py

from myproject.api.api import function_from_api

def test_function():
    print(function_from_api())

if __name__ == '__main__':
    test_function()

运行测试

(venv) PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
I am the return value from api.api!

*查看setuptools文档获取更多详细的setup.py示例。

**在现实中,您可以将虚拟环境放在硬盘上的任何地方。

您需要查看import语句是如何在相关代码中编写的。如果examples/example_one.py使用以下import语句:

import api.api

...然后,它期望项目的根目录位于系统路径中。

不需要任何hack(如你所说)就能支持它的最简单的方法就是从顶级目录运行这些例子,就像这样:

PYTHONPATH=$PYTHONPATH:. python examples/example_one.py 

项目

1.1用户

1.1.1 about.py

1.1.2 init.py

1.2技术

1.2.1 info.py

1.1.2 init.py

现在,如果你想访问User包中的about.py模块,从Tech包中的info.py模块,那么你必须将cmd(在windows中)路径带到项目中,即。 **C:\Users\Personal\Desktop\Project>**根据上面的包示例。你必须从这个路径输入python -m Package_name.module_name 例如,对于上面的包,我们必须做,

c:\用户\个人\桌面\项目>python -m Tech.info

小鬼点

不要在info模块后使用.py扩展名,即python -m Tech.info.py 输入this,其中兄弟包位于同一级别。 -m是标志,要检查它,你可以从CMD python——help