簡體   English   中英

python3中pytest的布局和導入

[英]Layout and importing for pytest in python3

我無法從pytest函數導入模塊。 我知道有100萬個問題,但我已經閱讀了一堆,但仍然難以理解。

$ tree
.
└── code
    ├── eight_puzzle.py
    ├── missionaries_and_cannibals.py
    ├── node.py
    ├── search.py
    └── test
        ├── test_eight_puzzle.py
        └── test_search.py

2 directories, 6 files
$
$ grep import code/test/test_search.py
import sys
import pytest
import code.search
$
$ pytest
...
ImportError while importing test module '~/Documents/code/test/test_search.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
code/test/test_search.py:14: in <module>
    import code.search
E   ModuleNotFoundError: No module named 'code.search'; 'code' is not a package
...

我希望那能奏效。 “代碼”是一個包,對嗎? Python 3中的軟件包是其中包含.py文件的任何目錄。

我也嘗試了相對導入- from .. import search -並得到以下結果。

ImportError while importing test module '~/Documents/code/test/test_search.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
code/test/test_search.py:14: in <module>
    from .. import search
E   ImportError: attempted relative import with no known parent package

我也嘗試修改的sys.path如圖所示這里 ,我指定PYTHONPATH,並添加初始化代碼和測試.py文件。

我可以在不使用setuptools之類的情況下使導入工作嗎? 這只是為了進行實驗,因此我寧願不處理開銷。

可能還需要注意的是我正在使用conda,因為當我將python 2 pip安裝的pytest與init .py文件一起使用時,它似乎可以正常工作。

有關不帶__init__.py文件的目錄的一些說明:

隱式名稱空間包

盡管沒有__init__.py的目錄在Python 3中是有效的導入源,但它不是常規包,而是隱式名稱空間包(有關詳細信息,請參見PEP 420 )。 除其他屬性外,隱式名稱空間包在導入時是二等公民,這意味着當Python在sys.path有兩個名稱相同的包時,一個是常規包,另一個是隱式命名空間包,即常規包。無論使用哪種軟件包,都將是首選。 自己檢查一下:

$ mkdir -p implicit_namespace/mypkg
$ echo -e "def spam():\n    print('spam from implicit namespace package')" > implicit_namespace/mypkg/mymod.py
$ mkdir -p regular/mypkg
$ touch regular/mypkg/__init__.py
$ echo -e "def spam():\n    print('spam from regular package')" > regular/mypkg/mymod.py
$ PYTHONPATH=implicit_namespace:regular python3 -c "from mypkg.mymod import spam; spam()"

這將打印spam from regular package :雖然implicit_namespace至上的sys.pathmypkg.mymodregular的進口,而不是因為regular/mypkg是一個普通的包。


現在您知道了,因為您的程序包code是隱式命名空間程序包,所以Python在遇到code導入時將更喜歡常規的code導入。 對於您來說不幸的是, stdlib中有一個模塊code ,因此實際上是一個“隱藏名稱”的問題:您有一個導入對象,其名稱與stdlib中的名稱相同,但不是隱藏了stdlib的導入,而是陰影了您的。

因此,您需要做兩件事才能使布局可用:

  1. code目錄一個唯一的名稱(對於這個答案的例子,讓它成為mycode
  2. 之后,從項目根目錄運行測試時,您仍然需要修復sys.path ,因為它本身不在sys.path 您有一些可能:
    • 將一個空的conftest.py文件添加到根目錄(除了mycode目錄)。 這將指示pytest將根目錄添加到sys.path (有關說明,請參見此處 )。 現在,您可以照常運行pytest ,導入將得到解決;
    • 通過python -m pytest運行測試-調用解釋器將當前目錄直接添加到sys.path ;
    • 通過PYTHONPATH env var將當前目錄添加到sys.path ,例如運行PYTHONPATH=. pytest PYTHONPATH=. pytest

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM