Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 兄弟包导入_Python_Packages_Python Import_Siblings - Fatal编程技术网

Python 兄弟包导入

Python 兄弟包导入,python,packages,python-import,siblings,Python,Packages,Python Import,Siblings,我试着通读有关兄弟姐妹导入的问题,甚至是 ,但我还没有找到答案 结构如下: ├── 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

我试着通读有关兄弟姐妹导入的问题,甚至是 ,但我还没有找到答案

结构如下:

├── 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
.
|__Main.py
|
|__Siblings
   |
   |___sib1
   |   |
   |   |__call.py
   |
   |___sib2
       |
       |__callsib.py
示例
测试
目录中的脚本如何从
api
模块,是否可以从命令行运行

另外,我希望避免对每个文件使用丑陋的
sys.path.insert
hack。当然
这可以在Python中完成,对吗?

您需要查看导入语句是如何在相关代码中编写的。如果
examples/example\u one.py
使用以下导入语句:

import api.api
…然后它希望项目的根目录位于系统路径中

在没有任何黑客攻击的情况下(如您所说),支持此操作的最简单方法是从顶级目录运行示例,如下所示:

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

您需要查看导入语句是如何在相关代码中编写的。如果
examples/example\u one.py
使用以下导入语句:

import api.api
…然后它希望项目的根目录位于系统路径中

在没有任何黑客攻击的情况下(如您所说),支持此操作的最简单方法是从顶级目录运行示例,如下所示:

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

首先,您应该避免使用与模块本身同名的文件。它可能破坏其他进口商品

导入文件时,解释器首先检查当前目录,然后搜索全局目录

示例
测试
中,您可以调用:

from ..api import api

首先,您应该避免使用与模块本身同名的文件。它可能破坏其他进口商品

导入文件时,解释器首先检查当前目录,然后搜索全局目录

示例
测试
中,您可以调用:

from ..api import api
七年后 自从我写了下面的答案之后,修改sys.path仍然是一个快速而肮脏的技巧,对于私有脚本来说效果很好,但是已经有了一些改进

  • 软件包(无论是否在virtualenv中)将为您提供所需的内容,不过我建议使用pip来实现这一点,而不是直接使用setuptools(并使用
    setup.cfg
    来存储元数据)
  • 作为一个包运行也很有效(但是如果你想把你的工作目录转换成一个可安装的包,结果会有点尴尬)
  • 对于测试,特别是在这种情况下,能够找到api包,并为您处理
    sys.path
    hacks
所以这取决于你想做什么。但是,在您的情况下,因为您的目标似乎是在某个时候制作一个合适的包,所以通过
pip-e
安装可能是您最好的选择,即使它还不完美

旧答案 正如在其他地方已经指出的,可怕的事实是,您必须进行丑陋的黑客攻击,以允许从
\uuuuu main\uuuu
模块从兄弟模块或父包导入。有关问题的详细信息,请参阅。试图以更合理的方式处理导入,但Guido拒绝了它

唯一的用例似乎是运行发生的脚本 住在一个模块的目录里,我一直认为这是一个 反模式

()

尽管如此,我还是经常使用这种模式

# Ugly hack to allow absolute import from the root folder
# whatever its name is. Please forgive the heresy.
if __name__ == "__main__" and __package__ is None:
    from sys import path
    from os.path import dirname as dir

    path.append(dir(path[0]))
    __package__ = "examples"

import api
这里的
path[0]
是您正在运行的脚本的父文件夹,而
dir(path[0])
是您的顶级文件夹

不过,我仍然无法使用相对导入,但它确实允许从顶层进行绝对导入(在您的示例
api
的父文件夹中)。

七年后 自从我写了下面的答案之后,修改sys.path仍然是一个快速而肮脏的技巧,对于私有脚本来说效果很好,但是已经有了一些改进

  • 软件包(无论是否在virtualenv中)将为您提供所需的内容,不过我建议使用pip来实现这一点,而不是直接使用setuptools(并使用
    setup.cfg
    来存储元数据)
  • 作为一个包运行也很有效(但是如果你想把你的工作目录转换成一个可安装的包,结果会有点尴尬)
  • 对于测试,特别是在这种情况下,能够找到api包,并为您处理
    sys.path
    hacks
所以这取决于你想做什么。但是,在您的情况下,因为您的目标似乎是在某个时候制作一个合适的包,所以通过
pip-e
安装可能是您最好的选择,即使它还不完美

旧答案 正如在其他地方已经指出的,可怕的事实是,您必须进行丑陋的黑客攻击,以允许从
\uuuuu main\uuuu
模块从兄弟模块或父包导入。有关问题的详细信息,请参阅。试图以更合理的方式处理导入,但Guido拒绝了它

唯一的用例似乎是运行发生的脚本 住在一个模块的目录里,我一直认为这是一个 反模式

()

尽管如此,我还是经常使用这种模式

# Ugly hack to allow absolute import from the root folder
# whatever its name is. Please forgive the heresy.
if __name__ == "__main__" and __package__ is None:
    from sys import path
    from os.path import dirname as dir

    path.append(dir(path[0]))
    __package__ = "examples"

import api
这里的
path[0]
是您正在运行的脚本的父文件夹,而
dir(path[0])
是您的顶级文件夹


不过,我仍然无法使用相对导入,但它确实允许从顶层(在您的示例
api
的父文件夹中)进行绝对导入。

我在
tests
文件夹的Python文件顶部插入了另一个替代方法:

# Path hack.
import sys, os
sys.path.insert(0, os.path.abspath('..'))

下面是我在
tests
文件夹中Python文件顶部插入的另一个备选方案:

# Path hack.
import sys, os
sys.path.insert(0, os.path.abspath('..'))

我还没有必要理解Pythonology,以了解在没有兄弟/相对导入黑客的情况下在无关项目之间共享代码的预期方式。直到那天,这是我的解决方案。对于
示例
测试
导入内容。\a
if __name__ == '__main__':
    if __package__ is None:
        import sys
        from os import path
        sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
        import api
    else:
        import ..api.api
.
└── 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
def function_from_api():
    return 'I am the return value from api.api!'
from api.api import function_from_api

def test_function():
    print(function_from_api())

if __name__ == '__main__':
    test_function()
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'
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
from setuptools import setup, find_packages

setup(name='myproject', version='1.0', packages=find_packages())
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]
(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
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!
.
|__Main.py
|
|__Siblings
   |
   |___sib1
   |   |
   |   |__call.py
   |
   |___sib2
       |
       |__callsib.py
import sib1.call as call


def main():
    call.Call()


if __name__ == '__main__':
    main()
import sib2.callsib as callsib


def Call():
    callsib.CallSib()


if __name__ == '__main__':
    Call()
def CallSib():
    print("Got Called")

if __name__ == '__main__':
    CallSib()
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
from setuptools import setup, find_packages

setup(name="PACKAGENAME", packages=find_packages())
pip install -e .