我试着通读关于兄弟姐妹导入的问题,甚至
软件包文档,但我还没找到答案。
结构如下:
├── 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中完成,对吧?
对于主要问题:
调用兄弟文件夹作为模块:
从. .进口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的文件夹,您可以将该文件夹或子文件夹中的每个脚本作为模块调用。
这是我用手机写的,很难设置成让每个人都能舒服地阅读。
对于主要问题:
调用兄弟文件夹作为模块:
从. .进口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的文件夹,您可以将该文件夹或子文件夹中的每个脚本作为模块调用。
这是我用手机写的,很难设置成让每个人都能舒服地阅读。
TLDR
这种方法不需要setuptools、路径hack、额外的命令行参数,也不需要在项目的每个文件中指定包的顶层。
只要在你调用的__main__的父目录中创建一个脚本,并从那里运行所有内容。进一步的解释请继续阅读。
解释
这可以在不使用新路径、额外的命令行参数或向每个程序添加代码来识别其兄弟程序的情况下完成。
这个失败的原因,我相信之前已经提到过,是被调用的程序将它们的__name__设置为__main__。当这种情况发生时,被调用的脚本接受自己位于包的顶层,并拒绝识别同级目录中的脚本。
但是,目录顶层下的所有内容仍然可以识别顶层下的任何其他内容。这意味着要让同级目录中的文件相互识别/利用,惟一需要做的就是从父目录中的脚本调用它们。
概念证明
在具有以下结构的目录中:
.
|__Main.py
|
|__Siblings
|
|___sib1
| |
| |__call.py
|
|___sib2
|
|__callsib.py
Main.py包含以下代码:
import sib1.call as call
def main():
call.Call()
if __name__ == '__main__':
main()
sib1 / call.py包含:
import sib2.callsib as callsib
def Call():
callsib.CallSib()
if __name__ == '__main__':
Call()
而sib2/ callsibb .py包含:
def CallSib():
print("Got Called")
if __name__ == '__main__':
CallSib()
如果你重现这个例子,你会注意到调用Main.py会导致“Got Called”被打印出来,就像在sib2/ callsibb .py中定义的那样,即使sib2/ callsibb .py是通过sib1/call.py调用的。但是,如果直接调用sib1/call.py(在对导入进行适当更改之后),则会抛出异常。即使它在其父目录中被脚本调用时可以工作,但如果它认为自己位于包的顶层,它就不能工作。