'ImportError: YadaYadaYada adında bir modül yok' pytest ile PATH sorunu


231

Ben bir mac üzerinde pytest yüklemek için easy_install kullandım ve böyle bir dosya yapısı ile bir proje için testler yazmaya başladı:

repo/
repo/app.py
repo/settings.py
repo/models.py
repo/tests/
repo/tests/test_app.py

çalıştırmak py.testrepo dizinde, her şey gibi hareket beklediğiniz süre

ama linux veya pencerelerde aynı şeyi denediğimde (her ikisinin de 2.2.3 üzerinde pytest var), uygulama yolumdan bir şeyin ilk içe aktarımına çarptığında havlar. Örneğin söylefrom app import some_def_in_app

Bu sistemlerde py.test çalıştırmak için PATH'ımı düzenlemem gerekir mi? Kimse bunu yaşadı mı?


4
İşte bunu setuptools ile düzeltmenin yolu.
ederag

4
Lütfen @hoefling cevabını kontrol edin ve eğer SO uzun süreden sonra izin veriyorsa, kabul ettiğiniz cevabı değiştirmeyi düşünün: çok daha iyi!
Davide

Yanıtlar:


91

Evet, eğer cdtest dizinine giderseniz kaynak klasör Python yolunda değildir .

2 seçeneğiniz var:

  1. Yolu test dosyalarına manuel olarak ekleyin.

    import sys, os
    myPath = os.path.dirname(os.path.abspath(__file__))
    sys.path.insert(0, myPath + '/../')
  2. Testleri env var PYTHONPATH=../.


11
cdbir dizine ne zaman giriyorum? Kökümden koşuyorum py.test. yanılmıyorsam ve sen piyon benim klasörleri yürüyor gibi demek
MattoTodd

bir cdsorun olsaydı, ben de mac'ta vurmaz mıydım?
MattoTodd

Oh, yanlış anladım ve testler dizininden işe yaramadığını düşündüm. yine de öneri 1'deki hile işe yarayacaktır. Yalnızca Linux kullanıyorum, bu yüzden diğer işletim sistemlerindeki davranışları açıklayamıyorum.
Not_a_Golfer

tüm test.py dosyalarınızda böyle bir içe aktarma işleminiz var mı?
MattoTodd

4
evet, ancak dizin yapım genellikle biraz farklı - genellikle / src ve / test kök dizini altında kalır.
Not_a_Golfer

275

Neden py.test PYTHONPATH içinde geçerli dizini eklemiyor emin değilim, ama burada bir geçici çözüm (deponuzun kökünden yürütülecek):

python -m pytest tests/

Python geçerli dizini sizin için PYTHONPATH'e eklediğinden çalışır.


2
Komutu yürüttüğünüz düzeyde değil, uygulamayı çalıştırmak için kodunuz varsa, göreli içe aktarmaları mutlak olanlara yeniden yazmanız gerekir. Örneğin: project/test/all-my-testsve project/src/app.pybu değişiklik nedeniyle, app.pybir __main__.pydosyayı kullanarak dolaylı olarak çağrılması gerekir project/src, böylece çağrı kullanılabilir python -m src. Anlayabildiğim kadarıyla oldukça dağınık şeyler.
Zelphir Kaltstahl

3
@Zelphir: Mutlak ithalat kullanmak önerilen bir uygulamadır. Habnabit'in en iyi ambalaj uygulamaları hakkında iyi bir makalesi var: blog.habnab.it/blog/2013/07/21/python-packages-and-you ve PEP8, "örtük göreceli ithalat asla kullanılmamalı ve Python'da kaldırılmamalıdır 3." Bkz . Python.org/dev/peps/pep-0008 .
Apteryx

1
@Apteryx "Proje mutlak" demek istiyorsun değil mi? Çünkü gibi şeyler /home/user/dev/projectxyz/src ...gerçekten kötü olurdu ve çoğu durumda diğer makinelerde çalışmaz. Ne demek istediğimi düşünüyorum, bir modül dosya çalıştırmak aynı klasörde olsa bile her zaman tüm proje kök modül yolu yazmak zorunda olduğunu düşünüyorum. Bunun en iyi uygulama olarak kabul edildiğini bilmiyordum, bu yüzden yararlı bir bilgi, teşekkürler. Hala mükemmel olmasa da, pep8'in çoğuna katılıyorum.
Zelphir Kaltstahl

1
@Zelphir, evet, demek istediğim buydu. Python'daki mutlak ithalat teriminin her zaman "proje mutlak" anlamına geldiğine inanıyorum. Bkz . Python.org/dev/peps/pep-0328/#rationale-for-absolute-imports . Aslında, en azından varsayılan "içe aktarma" mekanizmasını kullanarak rastgele, mutlak yol konumlarından içe aktaramayacağınızdan eminim.
Apteryx

4
__init__.pySorunu çözen testlere ekledim . Şimdi kullanabilirimpytest
Kiran Kumar Kotari

154

conftest çözüm

Az invaziv çözüm adında boş bir dosya ekliyor conftest.pyiçinde repo/dizinde:

$ touch repo/conftest.py

Bu kadar. Mangling için özel kod yazmanıza sys.pathveya sürüklemeyi PYTHONPATHveya __init__.pyait olmadığı yerlere yerleştirmeyi unutmayın .

Ardından proje dizini:

repo
├── conftest.py
├── app.py
├── settings.py
├── models.py
└── tests
     └── test_app.py

açıklama

pytestiçin görünüyor conftesttesti koleksiyonu modüllerin özel kancalar ve demirbaşlar toplamak ve onlardan özel nesneleri almak için için, pytestana dizini ekler conftest.pyiçinsys.path (bu durumda repodizinde).

Diğer proje yapıları

Eğer diğer proje yapınız varsa, koyun conftest.py(böylece vermez, paketleri içerir ancak bir paket kendisi değil one paket kök dir değil bir içerirler __init__.pyörneğin,):

repo
├── conftest.py
├── spam
   ├── __init__.py
   ├── bacon.py
   └── egg.py
├── eggs
   ├── __init__.py
   └── sausage.py
└── tests
     ├── test_bacon.py
     └── test_egg.py

src Yerleşim

Bu yaklaşım ile kullanılabilse de srcdüzeni (yer conftest.pyyer srcdir):

repo
├── src
   ├── conftest.py
   ├── spam
      ├── __init__.py
      ├── bacon.py
      └── egg.py
   └── eggs 
       ├── __init__.py
       └── sausage.py
└── tests
     ├── test_bacon.py
     └── test_egg.py

ekleyerek sakının srciçin PYTHONPATHazaltır anlam ve yararlarını srcdüzeni! Yüklü paketi değil kodu depodan test edeceksiniz. Yapmanız gerekiyorsa, belki de srcdir'e ihtiyacınız yoktur .

Buradan nereye gidilir

Tabii ki, conftestmodüller sadece kaynak kod bulmaya yardımcı olan bazı dosyalar değildir; pytestçerçevede projeye özgü tüm geliştirmelerin ve test paketinizin özelleştirilmesinin gerçekleştiği yer burasıdır . belgeleri boyunca dağılmış modüller pytesthakkında birçok bilgiye sahiptir ; başlangıç : dizin başına yerel eklentilerconftestconftest.py

Ayrıca, SO conftestmodüllerde mükemmel bir soruya sahiptir : py.test'te conftest.py dosyalarının kullanımı nedir?


2
@ aaa90210 Sorununuzu yeniden oluşturamama rağmen (bir kök dizinindeki bir yarışmadan içe aktarma herhangi bir düzeyde çalışır), ayrılmış bir ad olduğu için asla gizli dosyalardan içe aktarmamalısınız ve bunu yapmamanız pytestşiddetle tavsiye edilir. Bunu yaparak, gelecekteki hatalar için tohum ekersiniz. Adında başka bir modül oluşturun utils.pyve buradaki testlerde yeniden kullanmak için kodu yerleştirin.
Hoefling

4
Başparmak havaya! Bu benim için iyi sonuç veren tek çözüm.
130

4
kesinlikle kabul edilen cevap olmalı - teşekkür ederim!
Martin Peck

2
Mantıksal conftest.pyolarak, uygulama koduna ait değildir ve imo, altına yerleştirmek src/doğru değildir.
Nik O'Lai

2
Bu cevap SO üzerinde sabit bir başlık olmalıdır. Çok teşekkürler.
Rigoberta Raviolini

119

Ben de aynı problemi yaşadım. Dizime boş bir __init__.pydosya ekleyerek düzelttim tests.


77
Bu olduğunu Not DEĞİL py.test tarafından tavsiye: avoid “__init__.py” files in your test directories. This way your tests can run easily against an installed version of mypkg, independently from the installed package if it contains the tests or not.SRC: pytest.org/latest/goodpractises.html
K.-Michael Aye

24
Buraya aynı soru ile geldim ve __init__.pytestler dizinimden kaldırmanın benim için çözdüğünü buldum.
101

3
@mafro Sorunu görmüyorum? Testlerin içe aktarılabilir kod olması gerekmez, test çalıştırıcınız tarafından bulunur. Test edilmesi gereken sadece test edilecek kodun kurulu bir paket / modül olması gerekir.
K.-Michael Aye

5
İn __init__.pyalt dizinlerine eklenmesi, test/kurulacak modüllere karşı o alt dizindeki belirli testleri çalıştırmak için mutlak içe aktarma çalışması yapar. Teşekkürler.
Bryce Guinta

7
İşte gidin: doc.pytest.org/en/latest/goodpractices.html google ile bulmak gerçekten çok kolay.
K.-Michael Aye

46

pytestKendini bir modül olarak çalıştırın : python -m pytest tests


3
Bu işe yarayan bir çözüm gibi görünüyor, ama kimse NEDEN açıklayabilir? Altta yatan nedeni düzeltmek yerine python -m pytest"çünkü çalışır" dışında herhangi bir açıklama yapmadan kullanmak istiyorum
Janne Enberg

4
Bu, proje hiyerarşisi örneğin olduğunda package/src package/testsve testssizden içe aktardığınızda olur src. Bir modül olarak yürütme, içe aktarma işlemlerini yürütme konumuna göre mutlak olarak kabul eder.
Stefano Messina

1
Bu çözüm bana yardımcı oldu, teşekkürler! Bunun nedeni Python versiyonundaki çakışmadan kaynaklanıyordu. pytest testi önceki python sürümü için çalışır. Benim durumumda, python versiyonum 3.7.1, python -m pytest testleri çalışıyor ama pytest testleri değil.
Ruxi Zhang

1
Gönderen Pytest "piton -m pytest [...] yerine pytest ait [...] verimleri eski çağrı sys.path geçerli dizini katacak dışında neredeyse eşdeğer davranış. İle pytest Running"
Moad Ennagi

37

Proje kökünde PYTHONPATH ile çalışabilirsiniz

PYTHONPATH=. py.test

Veya pip install'i düzenlenebilir içe aktarma olarak kullanın

pip install -e .   # install package using setup.py in editable mode

3
Bu bir benim için işe yaramadı testdeğil dizinde srcdizin yapısı ve her iki içeren dizinden çağıran testve srcdizin.
Zelphir Kaltstahl

21

Bunu sorunuza ve kendi karışıklığımın cevabı olarak yarattım. Umut ediyorum bu yardım eder. Hem py.test komut satırında hem de tox.ini dosyasında PYTHONPATH öğesine dikkat edin.

https://github.com/jeffmacdonald/pytest_test

Özellikle: py.test ve tox'a dahil ettiğiniz modülleri nerede bulacağınızı söylemelisiniz.

Py.test ile bunu yapabilirsiniz:

PYTHONPATH=. py.test

Tox ile bunu tox.ini dosyasına ekleyin:

[testenv]
deps= -r{toxinidir}/requirements.txt
commands=py.test
setenv =
    PYTHONPATH = {toxinidir}

1
Bağlantı kurduğunuz proje için kısa bir açıklama yapabilir misiniz?
JF Meier

1
Belki de sadece ben, ama projedeki README oldukça ayrıntılı ve stackoverflow hakkındaki yorumum neden repoyu oluşturduğumu söylüyor.
Jeff MacDonald

5
Kesinlikle gerekli olmamakla birlikte, cevabın ana içeriğinin cevabın kendisinde bulunması olağan bir politikadır, çünkü cevabın, bağlantılı kaynağın çoktan gitmiş olabileceği x yıl sonra anlaşılabilir olmasını sağlar.
JF Meier

:) Oh iyi. Bu senin için internet.
Jeff MacDonald

9

Flask'ta da aynı sorunu yaşadım.

Eklediğimde:

__init__.py

test klasörü, sorun kayboldu :)

Muhtemelen uygulama klasör testlerini modül olarak tanıyamadı


8

__init__.pyKaynaklarımın üst klasöründeki üst düzey kaldırılarak düzeltildi .


1
Benim için düzelttim. Birisi bunu açıklayabilir mi?
aboger

buradaki bu benim için de düzeltildi. kimse varsa bu kesinlikle bir açıklama görmek
isterim

init .py ekledim ama hala aynı sorunlarla karşı karşıyaydı ama bu çözüm de benim için çalıştı .. neden lütfen?
Abhijit

7

ConftestImportFailure: ImportError('No module named ...Yanlışlıkla __init__.pysrc dizinime dosya eklediğimde garip hatalar almaya başladım .


3

Bu hatayı daha da basit bir şey yüzünden alıyordum (önemsiz bile diyebilirsiniz). Ben yüklü olmasaydı pytestmodülü. Yani basit bir apt install python-pytestsorun benim için düzeltildi.

'pytest' setup.py dosyasında test bağımlılığı olarak listelenirdi. Test gereksinimlerini de yüklediğinizden emin olun.


3

Benzer bir sorunum vardı. pytestçalıştığım ortamda kurulu bir modülü tanımıyordu.

pytestAynı ortama da kurarak çözdüm.


Bir venv içinden pytest kullanmama rağmen, küresel olarak da kurdum, bu da bana bu hatayı verdi. Global sürümü kaldırdıktan ve venv içine yükledikten sonra çalıştı.
Markus Ressel

2

Benim için sorun dizin tests.pyile birlikte Django tarafından oluşturuldu tests. Kaldırma tests.pysorunu çözdü.


2

Göreli içe aktarmaları yanlış kullandığım için bu hatayı aldım. OP örneğinde, test_app.py işlevi örn.

from repo.app import *

Ancak liberal __init__.py dosyaları dosya yapısı etrafında dağılmış, bu yok değil çalışmak ve dosyalar ve test dosyaların aynı dizinde olmadıkça görülen ImportError tür oluşturur.

from app import *

İşte projelerimden biriyle ne yapmak zorunda olduğumun bir örneği:

İşte benim proje yapısı:

microbit/
microbit/activity_indicator/activity_indicator.py
microbit/tests/test_activity_indicator.py

Etkinlik_indicator.py test_activity_indicator.py üzerinden erişmek için gerekli:

  • test_activity_indicatory.py dosyasını doğru göreceli içe aktarma ile başlatın:
    from microbit.activity_indicator.activity_indicator import *
  • __init__.py dosyalarını proje yapısı boyunca koy:
    microbit/
    microbit/__init__.py
    microbit/activity_indicator/__init__.py
    microbit/activity_indicator/activity_indicator.py
    microbit/tests/__init__.py
    microbit/tests/test_activity_indicator.py

0

Çok sık testler modülün içe aktarılamaması nedeniyle kesildi, Araştırmadan sonra, sistemin dosyaya yanlış yere baktığını öğrendim ve modülü içeren dosyayı kopyalayarak sorunu kolayca çözebiliriz. düzgün bir şekilde içe aktarmak için belirtilen klasörle aynıdır. Başka bir çözüm önerisi, içe aktarma bildirimini değiştirmek ve MutPy'ye birimin doğru yolunu göstermek olacaktır. Bununla birlikte, birden fazla birimin bu bağımlılığa sahip olabilmesi nedeniyle, bildirimlerinde de değişiklikler yapmamız gerektiği için birimi basitçe klasöre taşımayı tercih ediyoruz.


OP'nin sorusunu sağlayan başka cevaplar da var ve bunlar bir süre önce yayınlandı. Yanıt gönderirken, lütfen özellikle eski soruları yanıtlarken yeni bir çözüm veya çok daha iyi bir açıklama eklediğinizden emin olun. Bazen belirli bir cevaba yorum yapmak daha iyidir.
help-info.de

@ Help-info.de adresindeki yoruma ek olarak: Soruları cevaplamak için rehbere link: stackoverflow.com/help/how-to-answer
NOD'un eli

0

Dirk Avery tarafından yazılan bir mesaja göre size çapında bir sistem pytest yükleme o zaman bir kullanamaz projeniz için bir sanal ortam kullanıyorsanız (ve benim kişisel deneyim tarafından desteklenir); sanal ortama yüklemeniz ve bu yüklemeyi kullanmanız gerekir.

Özellikle, her iki yere de yüklediyseniz, pytestkomutun çalıştırılması sistem kurulumunu kullanacağı için çalışmaz. Diğer cevapların açıkladığı gibi, python -m pytestyerine basit bir çözüm çalıştırmaktır pytest; bu çalışır çünkü çevrenin pytest versiyonunu kullanır. Alternatif olarak, sistemin pytest sürümünü kaldırabilirsiniz; sanal ortamı yeniden etkinleştirdikten sonra pytestkomutun çalışması gerekir.


Benim için şimdiye kadar işe yarayan tek şey python -m pytest tests/.
Nik O'Lai

0

Flask eğitimini takip ederken de aynı problemi yaşıyordum ve resmi Pytest belgelerinde cevabı buldum .

setup.pyProjenizin kök dizininde en az aşağıdaki iki satırı içeren bir dosya oluşturmanız gerekir :

from setuptools import setup, find_packages
setup(name="PACKAGENAME", packages=find_packages())

Burada PACKAGENAME uygulamanızın adıdır. Sonra pip ile yüklemeniz gerekir:

pip install -e .

-eBayrak modu düzenlenebilir paketi intall veya "geliştirme" pip söyler. Bir dahaki sefere çalıştırdığınızda pytest, uygulamanızı standartta bulmalıdır PYTHONPATH.


0

Çözümüm:

aşağıdakini içeren dizinde conftest.pydosyayı testoluşturun:

import os
import sys
sys.path.insert(0,os.path.dirname(os.path.realpath(__file__)) + "/relative/path/to/code/")

Bu, her test dosyasını değiştirmeden , env değişkenini ayarlamadan veya mutlak / göreli yollarla karışıklık yapmadan ilgili klasörü python yoluna ekleyecektir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.