无法从其他目录导入python模块

qlvxas9a  于 2023-01-27  发布在  Python
关注(0)|答案(5)|浏览(170)

我在python3中有这样的代码结构:

- datalake
  __init__.py
  utils
     __init__.py
     utils.py
  lambdas
     __init__.py
     my-lambdas.py
- tests
    __init__.py
    demo.py

所有init__.py文件均为空。
我的问题是如何从tests/demo.py导入datalake模块?我尝试在demo.py中导入from datalake.utils import utils,但当我从命令行运行python tests/demo.py时,我得到这个错误ModuleNotFoundError: No module named 'datalake'
如果我使用这个代码:

from ..datalake.utils import utils

我将得到错误ValueError: attempted relative import beyond top-level package
我还尝试从my-lambda.py文件导入模块utils,也失败了。my-lambda.py中的代码是from datalake.utils import utils,但从命令行运行python datalake/lambda/my-lambda.py时,我得到ModuleNotFoundError: No module named 'datalake'错误。
如何导入模块?

8hhllhi2

8hhllhi21#

当你运行python tests/demo.py这样的命令时,你所在的文件夹不会被添加到PYTHONPATH中,脚本文件夹会被添加到PYTHONPATH中。因此,像import datalake这样的顶级导入将失败。要解决这个问题,你可以将测试作为一个模块运行:
巨蟒2:

python -m tests/demo

巨蟒3:

python -m tests.demo

并且demo.py中的任何datalake导入都将工作。
听起来你真正想做的是在你的主应用程序中建立一个包含测试的文件夹并运行它们。为此我推荐py.test,对于你的情况,你可以阅读应用程序代码外的测试来了解如何做。TL;DR是使用python -m py.test从顶层项目文件夹运行测试,它将正常工作。

h6my8fg2

h6my8fg22#

首先,my-lambdas.py不能用import语句导入,因为连字符在Python标识符中是无效的,请尝试遵循PEP-8的命名约定,例如mylambdas.py
否则,包结构看起来很好,并且只要你在datalake/之上的级别,它就应该是可导入的,例如,如果你在myproject/下面的目录:

myproject
├── datalake
│   ├── __init__.py
│   ├── utils
│   │   ├── __init__.py
│   │   └── utils.py
│   └── lambdas
│       ├── __init__.py
│       └── mylambdas.py
└── tests
    ├── __init__.py
    └── demo.py

那么这应该行得通:

~/myproject$ python -c 'from datalake import utils'

否则,将环境变量PYTHONPATH设置为datalake/之上的路径或修改sys.path都是改变Python导入位置的两种方法,更多信息请参见官方的tutorial on modules
还有一些一般性建议:我发现,在需要扩展之前,坚持使用简单的模块而不是包(目录)是很有用的,然后你可以将foo.py更改为foo/目录,其中包含__init__.py文件,import foo将像以前一样工作,尽管你可能需要向__init__.py添加一些导入来保持API兼容性,这将使你拥有一个更简单的结构:

myproject
├── datalake
│   ├── __init__.py
│   ├── utils.py
│   └── lambdas.py
└── tests
    ├── __init__.py
    └── demo.py
pgky5nke

pgky5nke3#

您可以将模块目录添加到sys.path中:

import sys
sys.path.append("your/own/modules/folder")  # like sys.path.append("../tests")

但这是一次性方法,仅在此时有效,添加的路径不是永久性的,代码执行完毕后会将其删除。

juud5qan

juud5qan4#

直接导入文件而不使用from的方法之一,如import util

wlwcrazw

wlwcrazw5#

您可以尝试运行:

python -m datalake.lambda.my-lambda

请访问:https://docs.python.org/3.7/using/cmdline.html#cmdoption-m

相关问题