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

时间:2019-07-26 01:21:33

标签: python python-3.x

我在python3中具有以下代码结构:

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

所有init__.py文件均为空。

我的问题是如何从datalake导入tests/demo.py模块? 我在from datalake.utils import utils中尝试过demo.py,但是当我从命令行运行python tests/demo.py时,出现此错误ModuleNotFoundError: No module named 'datalake'

如果我使用此代码:

from ..datalake.utils import utils

我将收到错误ValueError: attempted relative import beyond top-level package

我还尝试从utils文件导入模块my-lambda.py,但同样失败。 my-lambda.py中的代码为from datalake.utils import utils,但是从命令行运行ModuleNotFoundError: No module named 'datalake'时出现python datalake/lambda/my-lambda.py错误。

如何导入模块?

4 个答案:

答案 0 :(得分:2)

首先,my-lambdas.py不能与import语句一起导入,因为连字符在Python标识符中无效。尝试遵循PEP-8's naming conventions,例如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目录,尽管您可能需要向{{1} },以保持API兼容性。这将使您的结构更简单:

import foo

答案 1 :(得分:1)

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

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

但这是一种一次性方法,目前仅适用于此方法,添加的路径不是永久性的,在代码完成执行后将被消除。

答案 2 :(得分:1)

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

$ python -m tests/demo

以及datalake中的所有demo.py导入都可以使用。

听起来,您真正想要做的是拥有一个包含独立于主应用程序的测试的文件夹并运行它们。为此,我建议使用py.test,对于您的情况,您可以阅读Tests Outside Application Code以了解操作方法。 TL; DR使用python -m py.test从顶级项目文件夹运行测试,并且可以运行。

答案 3 :(得分:-2)

您可以尝试运行:

python -m datalake.lambda.my-lambda

关注:https://docs.python.org/3.7/using/cmdline.html#cmdoption-m