Jak poprawnie używać importu względnego lub bezwzględnego w modułach Pythona?

Użycie względnych importów w Pythonie ma jedną wadę, nie będziesz mógł już uruchamiać modułów jako samodzielnych, ponieważ otrzymasz wyjątek: ValueError: Attempted relative import in non-package

# /test.py: just a sample file importing foo module
import foo
...

# /foo/foo.py:
from . import bar
...
if __name__ == "__main__":
   pass

# /foo/bar.py: a submodule of foo, used by foo.py
from . import foo
...
if __name__ == "__main__":
   pass

Jak zmodyfikować przykładowy kod, aby móc wykonać wszystkie: test.py, foo.py i bar.py

Szukam rozwiązania, które działa z Pythonem 2.6+ (w tym 3.x).

Author: sorin, 2010-09-01

6 answers

Po pierwsze, zakładam, że zdajesz sobie sprawę z tego, co napisałeś, doprowadziłoby do okrągłego problemu z importem, ponieważ Foo importuje pasek i viceversa; spróbuj dodać

from foo import bar

To test.py i zobaczysz, że się nie powiedzie. Przykład musi zostać zmieniony, aby zadziałał.

Więc to, o co prosisz, to tak naprawdę powrót do importu bezwzględnego, gdy import względny nie powiedzie się; w rzeczywistości, jeśli wykonujesz foo.py lub bar.py jako główny moduł, pozostałe moduły będą po prostu leżeć na poziomie głównym, a jeśli dzielą nazwę z inny moduł w systemie, który zostanie wybrany, zależy od kolejności w sys./ align = "left" / Ponieważ bieżący katalog jest zwykle pierwszym, lokalne moduły będą wybierane, jeśli są dostępne - tzn. jeśli masz 'os.py' plik w bieżącym katalogu roboczym, zostanie wybrany zamiast wbudowanego.

Możliwą sugestią jest:

Foo.py

try:
    from . import bar
except ValueError:
    import bar

if __name__ == "__main__":
    pass

Bar.py:

if __name__ == "__main__":
    pass

Przy okazji wywołanie skryptów z odpowiedniej pozycji jest zwykle sposobem lepszym.

python -m foo.bar

Jest to chyba najlepszy sposób. Ten uruchamia moduł jako skrypt .

 16
Author: Alan Franzoni,
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-07-25 22:14:23

Możesz po prostu zacząć 'uruchamiać Moduły jako samodzielne' w nieco inny sposób:

Zamiast:

python foo/bar.py

Użycie:

python -mfoo.bar

Oczywiście plik foo/__init__.py musi być obecny.

Zwróć również uwagę, że masz Okrężną zależność między foo.py i bar.py – to nie zadziała. To chyba pomyłka w twoim przykładzie.

Update: wygląda na to, że działa również doskonale, aby użyć tego jako pierwszej linii foo/bar.py:

#!/usr/bin/python -mfoo.bar

Wtedy możesz wykonać skrypt bezpośrednio w systemach POSIX.

 22
Author: Jacek Konieczny,
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
2010-09-01 12:29:41

Porzuć względny import: powinieneś myśleć o swojej przestrzeni nazw pakietów jako o przestrzeni globalnej.

Sztuką tworzenia tego smacznego jest odpowiednie edytowanie sys.path. Oto coś do przemyślenia:

# one directory up
_root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.insert(0, _root_dir)for now
 1
Author: Edward Z. Yang,
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
2014-05-08 19:58:55

Potrzebujesz __init__.py w każdym folderze.

Względny import działa tylko wtedy, gdy:

python test.py

Test.py przywóz foo.py oraz foo.py może względnie importować cokolwiek z folderu test.py i wyżej.

You can ' t do:

cd foo
python foo.py
python bar.py
To nigdy nie zadziała. Możesz spróbować sys./ align = "left" / Dołącz lub sys./ align = "left" / Wstaw rozwiązanie ale zepsujesz ścieżki i będziesz miał problemy z F = open (nazwa pliku).
 1
Author: Dimitris D,
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-03-28 01:59:21

Dlaczego po prostu nie umieścić "main" w innym pliku .py?

 0
Author: Nathan Davis,
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
2010-09-06 02:55:52

Jak na razie jedynym rozwiązaniem, jakie znalazłem, było nieużywanie w ogóle importu względnego.

Ze względu na obecne ograniczenia, zastanawiam się, kiedy ktoś powinien używać względnych importów w Pythonie.

Na wszystkich konfiguracjach, które używałem sys.path zawiera bieżący katalog jako pierwszy argument, więc po prostu użyj import foo zamiast from . import foo, ponieważ zrobi to samo.

 -2
Author: bogdan,
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
2014-05-08 19:58:39