ข้อผิดพลาดในการนำเข้าจมูก Python


121

ดูเหมือนจะไม่สามารถรับกรอบการทดสอบจมูกได้เพื่อจดจำโมดูลใต้สคริปต์ทดสอบของฉันในโครงสร้างไฟล์ได้ ฉันได้สร้างตัวอย่างที่ง่ายที่สุดที่แสดงให้เห็นถึงปัญหา ฉันจะอธิบายไว้ด้านล่าง

นี่คือโครงสร้างไฟล์แพ็คเกจ:

./__init__.py
./foo.py
./tests
   ./__init__.py
   ./test_foo.py

foo.py ประกอบด้วย:

def dumb_true():
    return True

การทดสอบ / test_foo.py ประกอบด้วย:

import foo

def test_foo():
    assert foo.dumb_true()

ทั้งสอง ไฟล์init. pyว่างเปล่า

หากฉันรันnosetests -vvในไดเร็กทอรีหลัก (โดยที่ foo.py อยู่) ฉันจะได้รับ:

Failure: ImportError (No module named foo) ... ERROR

======================================================================
ERROR: Failure: ImportError (No module named foo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python/site-packages/nose-0.11.1-py2.6.egg/nose/loader.py", line 379, in loadTestsFromName
    addr.filename, addr.module)
  File "/usr/lib/python/site-packages/nose-0.11.1-py2.6.egg/nose/importer.py", line 39, in importFromPath
    return self.importFromDir(dir_path, fqname)
  File "/usr/lib/python/site-packages/nose-0.11.1-py2.6.egg/nose/importer.py", line 86, in importFromDir
    mod = load_module(part_fqname, fh, filename, desc)
  File "/home/user/nose_testing/tests/test_foo.py", line 1, in <module>
    import foo
ImportError: No module named foo

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (errors=1)

ฉันได้รับข้อผิดพลาดเดียวกันเมื่อฉันเรียกใช้จากภายในไดเรกทอรีการทดสอบ / ตามเอกสารและตัวอย่างที่ฉันพบจมูกควรจะเพิ่มแพ็กเกจพาเรนต์ทั้งหมดลงในพา ธ รวมถึงไดเร็กทอรีที่เรียกใช้ แต่ดูเหมือนจะไม่เกิดขึ้นในกรณีของฉัน

ฉันใช้ Ubuntu 8.04 พร้อม Python 2.6.2 ฉันได้สร้างและติดตั้งจมูกด้วยตนเอง (ไม่ใช่ด้วย setup_tools) หากเป็นเช่นนั้น

คำตอบ:


226

คุณมี__init__.pyอยู่ในไดเรกทอรีระดับบนสุดของคุณ นั่นทำให้มันเป็นแพ็คเกจ หากคุณลบออกคุณnosetestsควรจะใช้งานได้

หากคุณไม่ได้เอามันออกไปคุณจะมีการเปลี่ยนแปลงของคุณimportไปimport dir.fooที่dirเป็นชื่อของไดเรกทอรีของคุณ


7
ที่ได้รับมัน ขอบคุณมาก! ฉันจะโหวต แต่ดูเหมือนว่าฉันต้องการชื่อเสียงมากกว่านี้
halfak

4
ไม่ต้องห่วง. ยินดีต้อนรับสู่ StackOverflow! คุณสามารถติ๊กเครื่องหมายถูกสีเขียวทางด้านซ้ายหากคำตอบช่วยแก้ปัญหาของคุณได้
ire_and_curses

2
@halfak: มีการโหวตเพิ่มขึ้นอีกครั้งสำหรับคำถามของคุณแล้ว คุณก็เช่นกัน (ในคำตอบของคุณ) @ire
Mark Rushakoff

1
เข้าใจแล้ว ขอบคุณสำหรับเคล็ดลับ :)
halfak

5
ฉันมีสถานการณ์ที่การทดสอบทำงานหากinit .py ในไดเรกทอรีราก - อย่างไรก็ตามฉันต้องการให้ไฟล์นั้นอยู่ที่นั่นและยังไม่พบโมเดลการนำเข้า <model_name> การทดสอบอยู่ในไดเร็กทอรีการทดสอบ /และโมเดลที่ฉันพยายามทดสอบอยู่ในโมเดล /ไดเร็กทอรี ... ขอความช่วยเหลือใด ๆ
Kees Briggs

32

คุณอยู่ใน Virtualenv หรือไม่? ในกรณีของฉันnosetestsคืออัน/usr/bin/nosetestsที่ใช้/usr/bin/pythonอยู่ แพ็คเกจใน Virtualenv จะไม่อยู่ในเส้นทางของระบบอย่างแน่นอน ต่อไปนี้แก้ไขสิ่งนี้:

source myvirtualenv/activate
pip install nose
which nosetests
/home/me/myvirtualenv/bin/nosetests

2
ของฉันด้วย ขอบคุณช่วยประหยัดเวลาได้มาก
jskulski

3
สำหรับฉันnosetestsถูกแคชbashไปยังระบบหนึ่งใน/usr/local/bin(ในขณะที่which nosetestsให้ผลลัพธ์ที่เหมาะสม) ฉันใช้สิ่งนี้เพื่อล้างมัน
Raffi

5
นอกจากนี้ฉันต้องปิดการใช้งานและเปิดใช้งาน Virtualenv ของฉัน
Bengt

ฉันมีปัญหากับPS1 = $ {PS1: -} ที่ตั้งค่าเมื่อเปิดใช้งาน Virtualenv (เพื่อเอาชนะข้อผิดพลาดเกี่ยวกับตัวแปรที่ไม่ได้ตั้งค่า) หลังจากลบสิ่งนี้และเปลี่ยนเป็นset + uฉันก็ไม่มีปัญหาอีกต่อไป
Juuso Ohtonen

13

สำหรับผู้ที่พบคำถามนี้ในภายหลัง: ฉันได้รับข้อผิดพลาดในการนำเข้าหากไม่มีไฟล์ __init__.pyไฟล์ในไดเรกทอรีการทดสอบของฉัน

โครงสร้างไดเร็กทอรีของฉันเป็นแบบนี้:

./tests/
  ./test_some_random_stuff.py

หากฉันทำการทดสอบ nosetests:

nosetests -w tests

มันจะให้สิ่งImportErrorที่ทุกคนเห็น ถ้าฉันเพิ่ม__init__.pyไฟล์เปล่ามันก็ใช้ได้ดี:

./tests/
  ./__init__.py
  ./test_some_random_stuff.py

10

ปัญหาที่อาจเกิดขึ้นอีกประการหนึ่งคือยัติภังค์ / ขีดกลางในแผนผังไดเรกทอรี ฉันเพิ่งได้รับการแก้ไขปัญหาที่จมูก ImportError โดยการเปลี่ยนชื่อไดเรกทอรีจากไปsub-dirsub_dir



1
@Aman คุณตระหนักถึงความแตกต่างระหว่างตัวระบุตัวแปรและชื่อไฟล์หรือไม่?
Nakilon

ใช่ ... ฉันมักจะมีไฟล์ที่คล้ายกับ FooTests.py และด้วยเหตุผลบางอย่างที่ไม่ชอบ ... ฉันเปลี่ยนชื่อเป็น Foo_Tests.py และใช้งานได้ ... ดูเหมือนจะค่อนข้างจู้จี้จุกจิก
Birdman

3

แน่นอนว่าคุณมีข้อผิดพลาดทางไวยากรณ์ในโมดูลที่กำลังนำเข้าซึ่งจะทำให้เกิดสิ่งนี้ สำหรับฉันแล้วปัญหาเกิดขึ้นเมื่อฉันมีการสำรองข้อมูลของไฟล์ทดสอบด้วยพา ธ เช่น module / tests.bak.py ในไดเร็กทอรีเดียวกับ tests.py นอกจากนี้เพื่อจัดการกับปัญหาinit package / module ในแอป Django คุณสามารถเรียกใช้สิ่งต่อไปนี้ (ใน bash / OSX shell) เพื่อให้แน่ใจว่าคุณไม่มีไฟล์init. pyc ใด ๆอยู่รอบ ๆ :

find . -name '*.pyc' -delete

3

ฉันได้รับข้อความแสดงข้อผิดพลาดนี้เนื่องจากฉันเรียกใช้ไฟล์ nosetestsคำสั่งจากไดเรกทอรีที่ไม่ถูกต้อง

โง่ แต่เกิดขึ้น


คุณช่วยเพิ่มรายละเอียดในคำตอบของคุณได้ไหม คุณเรียกใช้ไดเรกทอรีใด ทำไมถึงทำผิด? ไดเรกทอรีที่ถูกต้องคืออะไร? การรันnosetestsในไดเร็กทอรีโดยไม่มีการทดสอบRan 0 testsใด ๆจะส่งผลให้ไม่มีข้อผิดพลาดในการนำเข้า คำตอบนี้ไม่มีประโยชน์ในรูปแบบปัจจุบัน
gerrit

2

ฉันเพียงแค่วิ่งเข้าไปในอีกหนึ่งสิ่งที่อาจก่อให้เกิดปัญหานี้: testname.test.pyการตั้งชื่อของการทดสอบในรูปแบบ สิ่งนี้.ทำให้จมูกสับสนและนำไปสู่การนำเข้าสิ่งที่ไม่ควร ฉันคิดว่าอาจเห็นได้ชัดว่าการใช้รูปแบบการตั้งชื่อการทดสอบที่ไม่เป็นทางการจะทำลายสิ่งต่าง ๆ แต่ฉันคิดว่ามันน่าสังเกต


2

ตัวอย่างเช่นกับโครงสร้างไดเรกทอรีดังต่อไปนี้ถ้าคุณต้องการที่จะทำงานnosetestsในm1, m2หรือm3เพื่อทดสอบฟังก์ชั่นบางอย่างในn.pyคุณควรใช้ในfrom m2.m3 import ntest.py

m1
└── m2
    ├── __init__.py
    └── m3
        ├── __init__.py
        ├── n.py
        └── test
            └── test.py

1

เพียงเพื่อตอบคำถาม: หากคุณกำลังดิ้นรนกับโครงสร้างเช่นนี้:

project
├── m1
    ├── __init__.py
    ├── foo1.py
    └──m2
       ├── __init__.py
       └── foo2.py

└── test
     ├── __init__.py
     └── test.py

และบางทีคุณอาจต้องการเรียกใช้การทดสอบจากเส้นทางภายนอกโครงการรวมเส้นทางโครงการของคุณไว้ใน PYTHONPATH ของคุณ

export PYTHONPATH=$PYTHONPATH:$HOME/path/to/project

วางไว้ใน. profile หากคุณอยู่ภายใต้สภาพแวดล้อมเสมือนจริงให้วางไว้ในการเปิดใช้งานในรูท venv ของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.