[英]Attempted relative import with no known parent package error
Error: While importing "wsgi-contract-test", an ImportError was raised:
Traceback (most recent call last):
File "/Users/karl/Development/tral/bin/tral-env/lib/python3.9/site-packages/flask/cli.py", line 236, in locate_app
__import__(module_name)
File "/Users/karl/Development/tral/test/contract/inject/wsgi-contract-test.py", line 8, in <module>
from . import (
ImportError: attempted relative import with no known parent package
ERROR (run-tral): trap on error (rc=2) near line 121
make: *** [component.mk:114: tral-local-run-api-contract-test] Error 2
wsgi-contract-test.py: wsgi-合同-test.py:
from ...libs.tral import app, setup_from_env
from ...libs.tral import routes
I have the regular source files under the libs/tral
directory, however the entry file for this test is located under test/contract/inject
.我在
libs/tral
目录下有常规源文件,但是此测试的入口文件位于test/contract/inject
下。 I do NOT want to move this test file into libs since this file should be nowhere near production code as it is a rather hazardous file security wise.我不想将这个测试文件移动到库中,因为这个文件应该远离生产代码,因为它是一个相当危险的文件安全性。
In node.js this would of worked fine but there seems to be something with python imports I'm not grasping?在 node.js 中,这可以正常工作,但 python 进口似乎有些东西我没有掌握?
Since tests don't belong inside the src
tree, there are basically two approaches.由于测试不属于
src
树,因此基本上有两种方法。 If you are testing a library you will frequently install it (in a virtualenv) and then just import it exactly the same way you would anywhere else.如果您正在测试一个库,您将经常安装它(在 virtualenv 中),然后以与其他任何地方完全相同的方式导入它。 Frequently you also do this with a fresh install for the test: this has the great advantage that your tests mirror real setups, and helps to catch bugs like forgetting to commit/include files (guilty.) and only noticing once you've deployed...
通常,您还可以通过全新安装测试来执行此操作:这具有很大的优势,即您的测试反映了真实的设置,并有助于捕获诸如忘记提交/包含文件(有罪)之类的错误,并且只有在部署后才注意到。 ..
The other option is to modify sys.path
so that your test is effectively in the same place as your production code:另一种选择是修改
sys.path
以便您的测试有效地与您的生产代码位于同一位置:
# /test/contract/inject.py
from pathlib import Path
import sys
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
Since sys.path
uses strs you may prefer to use os.path
, like every single other example on SO.由于
sys.path
使用 strs 您可能更喜欢使用os.path
,就像 SO 上的每个其他示例一样。 Personally I'm addicted to pathlib.就我个人而言,我沉迷于 pathlib。 Here:
这里:
__file__
is the absolute path of the current file __file__
是当前文件的绝对路径Path(str)
wraps it in a pathlib.Path
object Path(str)
将其包装在pathlib.Path
object.parent
gets you up the tree, and .parent
让你上树,然后str()
casts back to the format sys.path expects, or it won't work. str()
转换回 sys.path 期望的格式,否则它将不起作用。Normally we use a test runner for tests.通常我们使用测试运行器进行测试。 But these tests need a running instance: No problem:
但是这些测试需要一个正在运行的实例:没问题:
# tests/conftest.py
import pytest
from sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
# now pytest can find the src
from app import get_instance # dummy
@pytest.fixture
def instance():
instance = get_instance(some_param)
# maybe
instance.do_some_setup()
yield instance
# maybe
instance.do_some_cleanup()
If you don't need to do any cleanup, you can just return
the instance rather than yielding it.如果您不需要进行任何清理,则可以只
return
实例而不是产生它。 Then in another file (for neatness) you write tests like this:然后在另一个文件(为了整洁)中编写如下测试:
# tests/test_instance.py
def test_instance(instance): # note how we requested the fixture
assert instance.some_method()
And you run your tests with pytest:然后使用 pytest 运行测试:
pytest tests/
Pytest will run the code in conftest.py
, discover all test fns starting with test
in files whose names start with test
, run the tests (supplying all the fixtures you have defined) and report. Pytest 将运行 conftest.py 中的代码,在名称以
test
开头的文件中发现所有以 test 开头的test
conftest.py
,运行测试(提供您定义的所有夹具)并报告。
Sometimes spinning up a fixture can be expensive.有时旋转固定装置可能很昂贵。 See the docs on fixture scope for telling pytest to keep the fixture around and supply it to multiple tests.
请参阅夹具 scope上的文档,告诉 pytest 将夹具保持在周围并将其提供给多个测试。
You don't have to use a runner.您不必使用跑步者。 But they do have many advantages:
但它们确实有很多优点:
I took for granted that Python was able to handle simple relative paths;我理所当然地认为 Python 能够处理简单的相对路径; not the case.
不是这样。 Instead I just added the path to the packages I wanted to include in the
PYTHONPATH
variable and walla, it found everything.相反,我只是添加了我想要包含在
PYTHONPATH
变量和 walla 中的包的路径,它找到了所有内容。
export PYTHONPATH="${PYTHONPATH}:$(pwd)/libs"
Then running it from the root project directory.然后从根项目目录运行它。
I had to change the code to the following though:我不得不将代码更改为以下内容:
from tral import app, setup_from_env
from tral import routes
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.