简体   繁体   English

Python 无法从同一 package 中的模块导入 function

[英]Python cannot import function from module in same package

I have this package structure我有这个 package 结构

project/
    package_a/
        __init__.py
        subpackage_b/
            __init__.py
            module_one.py
        subpackage_c
            __init__.py
            module_two.py
    package_b/

module_one.py module_one.py

def test_func():
     return 0

How can I import test_func from module_two.py?如何从 module_two.py 导入test_func I have tried using我试过使用

from subpackage_b.module_one import test_func

from package_a.subpackage_b.module_one import test_func

from module_one import test_func

but none of them works, giving me ModuleNotFoundError .但它们都不起作用,给了我ModuleNotFoundError I understand there are many similar questions here but none of them seems to work for me.我知道这里有很多类似的问题,但似乎没有一个对我有用。 One which I have not tried is setting the PYTHONPATH variable, but I am not sure what to set it to.我没有尝试过的一个是设置PYTHONPATH变量,但我不确定将其设置为什么。 I am using VSCode and the current python.pythonPath is just the python file in my venv folder.我正在使用 VSCode,当前的python.pythonPath只是我的 venv 文件夹中的 python 文件。

You can find the set of paths that you can import from using您可以找到可以从中导入的一组路径

import sys
print(sys.path)

So, make sure that the project path is in sys.path .因此,请确保项目路径位于sys.path中。 If it is not, then you can add it dynamically in your code with the following line, which should be run before your import statements如果不是,那么您可以使用以下行在代码中动态添加它,这应该在您的导入语句之前运行

sys.path.append('C:/Path_to_project/project')

However, if you were running python from the project folder, the path should already be there.但是,如果您从项目文件夹中运行 python,则路径应该已经存在。

The proper way to import when your sys.path is including your project folder, would be当您的sys.path包含您的项目文件夹时,正确的导入方法是

from package_a.subpackage_b.module_one import test_func

In python, When the interpreter executes the import statement, it searches for module in a list of directories assembled from the following sources:在 python 中,当解释器执行import语句时,它在从以下来源组装的目录列表中搜索模块:

  • The directory from which the input script was run, or the current directory if the interpreter is being run interactively运行输入脚本的目录,或当前目录(如果解释器以交互方式运行)
  • The list of directories contained in the PYTHONPATH environment variable, if it is set. PYTHONPATH环境变量中包含的目录列表(如果已设置)。 (The format for PYTHONPATH is OS-dependent but should mimic the PATH environment variable.) PYTHONPATH的格式取决于操作系统,但应该模仿PATH环境变量。)
  • An installation-dependent list of directories configured at the time Python is installed (For example: in linux, /usr/local/lib/python )在安装 Python 时配置的依赖于安装的目录列表(例如:在 linux、 /usr/local/lib/python中)

In addition, You can put the module file in any directory of your choice and then modify sys.path at run-time so that it contains that directory but this would not be a standard.此外,您可以将模块文件放在您选择的任何目录中,然后在运行时修改sys.path以使其包含该目录,但这不是标准。 you can do it for internal purpose but not a best practice to share your code with this.您可以出于内部目的这样做,但不是与此共享代码的最佳实践。

Rather you can use python's __file__ attribute, to get the path and put it in sys.path like below:相反,您可以使用 python 的__file__属性来获取路径并将其放在sys.path中,如下所示:

import sys
from os.path import dirname
sys.path.append(dirname(__file__)) 

The root is of course your sys.path , and to answer why it does not work for you, I'll assume you attempt to invoke a python file from within your package, which will not allow python to find your package root properly. The root is of course your sys.path , and to answer why it does not work for you, I'll assume you attempt to invoke a python file from within your package, which will not allow python to find your package root properly.

Instead, invoke your code from a file directly in your project root (so the package is in the same directory as your main script file).相反,直接从项目根目录中的文件调用代码(因此 package 与主脚本文件位于同一目录中)。

From https://docs.python.org/3/library/sys.html#sys.path来自https://docs.python.org/3/library/sys.html#sys.path

As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter.在程序启动时初始化时,此列表的第一项路径 [0] 是包含用于调用 Python 解释器的脚本的目录。

$ tree
.
├── main.py
└── package_a
    ├── __init__.py
    ├── subpackage_b
    │   ├── __init__.py
    │   └── module_one.py
    └── subpackage_c
        ├── __init__.py
        └── module_two.py
# cat main.py 
import package_a.subpackage_c.module_two

# cat package_a/subpackage_b/module_one.py 
def test_func():
    return 0

# cat package_a/subpackage_c/module_two.py 
from package_a.subpackage_b.module_one import test_func
print("test func:", test_func())
$ python package_a/subpackage_c/module_two.py 
Traceback (most recent call last):
  File "package_a/subpackage_c/module_two.py", line 1, in <module>
    from package_a.subpackage_b.module_one import test_func
ModuleNotFoundError: No module named 'package_a'

$ python main.py
test func: 0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM