Jak naprawić "Attempted relative import in non-package" nawet z init.py

Próbuję śledzić PEP 328 , z następującą strukturą katalogów:

pkg/
  __init__.py
  components/
    core.py
    __init__.py
  tests/
    core_test.py
    __init__.py

W core_test.py mam następującą deklarację importu

from ..components.core import GameLoopEvents

Jednak, gdy biegam, dostaję następujący błąd:

tests$ python core_test.py 
Traceback (most recent call last):
  File "core_test.py", line 3, in <module>
    from ..components.core import GameLoopEvents
ValueError: Attempted relative import in non-package

Szukając wokół znalazłem "względna ścieżka nie działa nawet z __init__.py " i " Import modułu ze ścieżki względnej", ale nie pomogły.

Czy coś mi umyka?
Author: Community, 2012-07-18

12 answers

Tak. Nie używasz go jako paczki.

python -m pkg.tests.core_test
 376
Author: Ignacio Vazquez-Abrams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-18 08:01:04

Do rozwinięcia Ignacio Vazquez-Abrams ' s ODPOWIEDŹ:

Mechanizm importu Pythona działa względem __name__ bieżącego pliku. Gdy wykonujesz plik bezpośrednio, nie ma on zwykłej nazwy, ale zamiast niej ma "__main__". Więc względny Import nie działa.

Możesz, jak zasugerował Igancio, wykonać go za pomocą opcji -m. Jeśli masz część pakietu, która ma być uruchomiona jako skrypt, możesz również użyć atrybutu __package__, aby powiedzieć temu plikowi, co nazwa, którą powinien mieć w hierarchii pakietów.

Zobacz http://www.python.org/dev/peps/pep-0366 / Po szczegóły.

 547
Author: BrenBarn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-25 11:02:57

Możesz użyć import components.core bezpośrednio, jeśli dodasz bieżący katalog do sys.path:

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
 192
Author: ihm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-22 19:44:29

To zależy od tego, jak chcesz uruchomić skrypt.

Jeśli chcesz uruchomić swój UnitTest z linii poleceń w klasyczny sposób, to znaczy:

python tests/core_test.py

Następnie, ponieważ w tym przypadku 'components' i 'tests' są folderami rodzeństwa, możesz zaimportować względny moduł używając metody insert lub append. sys.ścieżka moduł. Coś w stylu:

import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents

W przeciwnym razie możesz uruchomić swój skrypt z argumentem'- m ' (zauważ, że w tym przypadku mówimy o pakiecie, dlatego nie możesz podawać rozszerzenia '. py ' ), czyli:

python -m pkg.tests.core_test

W takim przypadku możesz po prostu użyć względnego importu tak, jak to robiłeś:

from ..components.core import GameLoopEvents

Możesz w końcu wymieszać te dwa podejścia, aby twój skrypt działał bez względu na to, jak jest nazywany. Na przykład:

if __name__ == '__main__':
    if __package__ is None:
        import sys
        from os import path
        sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
        from components.core import GameLoopEvents
    else:
        from ..components.core import GameLoopEvents
 161
Author: Paolo Rovelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-10 16:55:01

W core_test.py, wykonaj następujące czynności:

import sys
sys.path.append('../components')
from core import GameLoopEvents
 13
Author: Allan Mwesigwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-10 17:44:57

Jeśli twój przypadek użycia jest do uruchamiania testów, i szwy, że jest, to możesz zrobić następujące. Zamiast uruchamiać skrypt testowy jako python core_test.py Użyj frameworka testowego, takiego jak pytest. Następnie w wierszu poleceń możesz wpisać

$$ py.test

To uruchomi testy w Twoim katalogu. Chodzi o kwestię __name__ bycia __main__, na którą zwrócił uwagę @BrenBarn. Następnie umieść pusty plik __init__.py w katalogu testowym, co uczyni katalog testowy częścią Twojego pakietu. Wtedy będziesz able to do

from ..components.core import GameLoopEvents

Jednakże, jeśli uruchomisz skrypt testowy jako główny program, to wszystko po raz kolejny się nie powiedzie. Więc po prostu użyj biegacza testowego. Może to działa również z innymi biegaczami testowymi, takimi jak nosetests, ale nie sprawdzałem tego. Mam nadzieję, że to pomoże.

 9
Author: deepak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-13 17:00:09

Moim szybkim rozwiązaniem jest dodanie katalogu do ścieżki:

import sys
sys.path.insert(0, '../components/')
 4
Author: v4gil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-01 07:19:41

Stary wątek. Dowiedziałem się, że dodanie __all__= ['submodule', ...] do __init__.py Plik, a następnie użycie from <CURRENT_MODULE> import * w celu działa dobrze.

 2
Author: Laurent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-18 17:13:32

Jeśli ktoś szuka obejścia, natknąłem się na jedno. Oto trochę kontekstu. Chciałem przetestować jedną z metod, które mam w pliku. When I run it from within

if __name__ == "__main__":
[1]}zawsze skarżył się na względny przywóz. Próbowałem zastosować powyższe rozwiązania, ale nie udało mi się, ponieważ było wiele zagnieżdżonych plików, każdy z wieloma importami. Oto co zrobiłem. Właśnie stworzyłem launcher, zewnętrzny program, który importowałby niezbędne metody i wywoływał je. Chociaż nie jest to świetne rozwiązanie, to działa.
 0
Author: HappyWaters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-21 10:17:58

Spróbuj tego

import components
from components import *
 0
Author: Vaishnavi Bala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-24 05:41:17

Możesz użyć from pkg.components.core import GameLoopEvents, Na przykład używam pycharm, poniżej jest mój obraz struktury projektu, po prostu importuję z pakietu root, potem działa:

Tutaj wpisz opis obrazka

 0
Author: Jayhello,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-14 11:20:11

Jak powiedział Paolo, mamy 2 metody wywoływania:

1) python -m tests.core_test
2) python tests/core_test.py

Jedna różnica między nimi to sys.Path [0] string. Ponieważ interpretacja będzie przeszukiwać sys.path podczas importowania możemy wykonać za pomocą tests/core_test.py:

if __name__ == '__main__':
    import sys
    from pathlib import Path
    sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
    from components import core
    <other stuff>

I więcej po tym, możemy uruchomić core_test.py z innymi metodami:

cd tests
python core_test.py
python -m core_test
...

Uwaga, py36 testowane tylko.

 0
Author: zhengcao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-20 08:01:03