我试着通读关于兄弟姐妹导入的问题,甚至
软件包文档,但我还没找到答案。
结构如下:
├── 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中完成,对吧?
存在的问题:
你只是不能让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
对于2021年的读者:如果你对pip没有信心,请安装-e:
考虑一下这个层次结构,正如Python 3中相对导入的答案所推荐的那样:
MyProject
├── src
│ ├── bot
│ │ ├── __init__.py
│ │ ├── main.py
│ │ └── sib1.py
│ └── mod
│ ├── __init__.py
│ └── module1.py
└── main.py
main.py的内容,这是起点,我们在这里使用绝对导入(没有前导点):
from src.bot import main
if __name__ == '__main__':
main.magic_tricks()
bot/main.py的内容,它利用了显式的相对导入:
from .sib1 import my_drink # Both are explicit-relative-imports.
from ..mod.module1 import relative_magic
def magic_tricks():
# Using sub-magic
relative_magic(in=["newbie", "pain"], advice="cheer_up")
my_drink()
# Do your work
...
原因如下:
当执行python MyProject/main.py时,/到/MyProject的路径被添加到sys.path中。
绝对导入import src。机器人会读的。
从…mod部分意味着它将上升一级到MyProject/src。
我们能看看吗?是的,因为路径/to/MyProject被添加到sys.path中。
所以重点是:
我们应该把主脚本放在MyProject/src旁边,因为当做相对引用时,我们不会离开src,绝对导入导入src。为我们提供合适的作用域:src/ scope。
参见:ModuleNotFoundError:没有名为“sib1”的模块
如果您正在使用pytest,那么pytest文档描述了如何从单独的测试包引用源包的方法。
建议的项目目录结构为:
setup.py
src/
mypkg/
__init__.py
app.py
view.py
tests/
__init__.py
foo/
__init__.py
test_view.py
bar/
__init__.py
test_view.py
setup.py文件的内容:
from setuptools import setup, find_packages
setup(name="PACKAGENAME", packages=find_packages())
以可编辑模式安装软件包:
pip install -e .
这篇文章引用了Ionel Cristian matrie什的博客文章。