假设存储库有一个./example用__init__.py文件调用的目录,以表明它是一个包。测试位于 中./tests,它没有文件__init__.py:
.
|-- README.md
|-- example
| |-- __init__.py
| `-- func.py
|-- setup.py
`-- tests
`-- test_hello.py
Run Code Online (Sandbox Code Playgroud)
./example/func.py很简单:
def hello():
return "hello!"
Run Code Online (Sandbox Code Playgroud)
如果我在根目录中运行交互式解释器,我可以导入example:
$ python
>>> import example
>>> example.hello()
'hello!'
Run Code Online (Sandbox Code Playgroud)
我还可以在导入的根目录中放置一个脚本example:
$ cat > temp.py
import example
print(example.hello())
^D
$ python temp.py
hello!
Run Code Online (Sandbox Code Playgroud)
这就是事情变得奇怪的地方。如果我pytest在不带参数的根目录中运行,它将无法导入example:
$ pytest
ImportError while importing test module '/Users/gregwilson/example/tests/test_hello.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
../conda/envs/stjs/lib/python3.9/importlib/__init__.py:127: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
tests/test_hello.py:1: in <module>
import example
E ModuleNotFoundError: No module named 'example'
Run Code Online (Sandbox Code Playgroud)
python -m pytest但是,如果我在根目录中运行它会起作用:
$ python -m pytest
collected 1 item
tests/test_hello.py .
Run Code Online (Sandbox Code Playgroud)
如果我现在添加一个空文件tests/__init__.py,测试将以两种方式进行:
$ touch tests/_init__.py
$ python -m pytest
collected 1 item
tests/test_hello.py .
$ pytest
collected 1 item
tests/test_hello.py .
Run Code Online (Sandbox Code Playgroud)
我的问题是:
pytest失败但python -m pytest在添加之前就可以工作./tests/__init__.py?__init__.py文件来tests制作pytest它自己的工作?但是等等,事情变得更奇怪了。我可以创建一个目录./temp并添加一个./temp/temp.py导入example并尝试使用它的文件:
$ mkdir temp
$ cat > temp/temp.py
import example
print(example.hello())
^D
Run Code Online (Sandbox Code Playgroud)
直接运行是不行的:
$ python temp/temp.py
ModuleNotFoundError: No module named 'example'
Run Code Online (Sandbox Code Playgroud)
运行它python -m:
$ python -m temp.temp
hello!
Run Code Online (Sandbox Code Playgroud)
但与这种tests情况不同的是,添加__init__.py文件并./temp 不会使其工作:
$ touch temp/__init__.py
$ python temp/temp.py
ModuleNotFoundError: No module named 'example'
Run Code Online (Sandbox Code Playgroud)
如果有人能解释这里发生了什么,我将不胜感激。