Dlaczego Python uruchamia mój moduł, kiedy go importuję i jak go zatrzymać?

173

Mam program w języku Python, który tworzę, który można uruchomić na dwa sposoby: pierwszy to wywołanie „python main.py”, który w przyjazny sposób prosi użytkownika o wprowadzenie danych, a następnie uruchamia dane wejściowe użytkownika za pośrednictwem programu. Innym sposobem jest wywołanie "python batch.py -file- ", który przejdzie przez wszystkie przyjazne zbieranie danych wejściowych i uruchomi cały plik wejściowy przez program za jednym razem.

Problem polega na tym, że kiedy uruchamiam "batch.py", importuje on niektóre zmienne / metody / etc z "main.py", a kiedy uruchamia ten kod:

import main

w pierwszym wierszu programu natychmiast wyświetla błąd, ponieważ próbuje uruchomić kod z pliku „main.py”.

Jak mogę powstrzymać Pythona od uruchamiania kodu zawartego w module „głównym”, który importuję?

Dasmowenator
źródło

Odpowiedzi:

251

Ponieważ tak właśnie działa Python - słowa kluczowe takie jak classi niedefdeklaracjami . Zamiast tego są prawdziwymi instrukcjami na żywo, które są wykonywane. Gdyby nie zostały wykonane, twój moduł byłby ... pusty :-)

W każdym razie idiomatyczne podejście to:

# stuff to run always here such as class/def
def main():
    pass

if __name__ == "__main__":
   # stuff only to run when not called via 'import' here
   main()

Zobacz, do czego służy if __name__ == "__main__"?

Wymaga to jednak kontroli źródła nad edytowanym modułem import.

Miłego kodowania.


źródło
1
żeby potwierdzić, twój komentarz "rzeczy uruchamiane tylko wtedy, gdy nie są wywoływane przez 'import' tutaj" sugerują polecenia, które mają być napisane pod main (), prawda? Czy to nie ma znaczenia?
Goldname
@Goldname Kod wewnątrz instrukcji if nie zostanie uruchomiony po zaimportowaniu, ale główna funkcja sama w sobie jest zdefiniowana i gotowa do użycia nawet podczas importu. Ten moduł po prostu wykonywałby główną funkcję po uruchomieniu i nie wykonywałby jej, gdyby był importowany. Wszystko zależy od tego, co chcesz robić. Jeśli nie potrzebujesz poleceń w main gdzie indziej, koniecznie zapisz je wewnątrz if. Ale dla mnie wygląda schludniej.
Felix,
51

Ze względu na sposób działania Pythona konieczne jest, aby uruchamiał moduły podczas ich importu.

Aby zapobiec wykonywaniu kodu w module po zaimportowaniu, ale tylko wtedy, gdy jest uruchamiany bezpośrednio, możesz go chronić za pomocą tego if:

if __name__ == "__main__":
    # this won't be run when imported

Możesz chcieć umieścić ten kod w main()metodzie, abyś mógł wykonać plik bezpośrednio lub zaimportować moduł i wywołać plik main(). Na przykład załóżmy, że to jest w pliku foo.py.

def main():
    print "Hello World"

if __name__ == "__main__":
    main()

Ten program można uruchomić, przechodząc python foo.pylub z innego skryptu Pythona:

import foo

...

foo.main()
Jeremy Banks
źródło
12

Użyj if __name__ == '__main__'idiomu - __name__to specjalna zmienna, której wartość '__main__'określa, czy moduł jest uruchamiany jako skrypt, a nazwa modułu, jeśli jest importowany. Więc zrobiłbyś coś takiego

# imports
# class/function definitions
if __name__ == '__main__':
    # code here will only run when you invoke 'python main.py'
Ismail Badawi
źródło
4

Niestety nie. To jest część tego, jak działa składnia importu i ważne jest, aby tak było - pamiętaj, że deffaktycznie coś jest wykonywane, gdyby Python nie wykonał importu, utknąłbyś bez funkcji.

Ponieważ jednak prawdopodobnie masz dostęp do pliku, możesz sprawdzić, co powoduje błąd. Może być możliwe zmodyfikowanie środowiska, aby zapobiec występowaniu błędu.

cwallenpoole
źródło
1
Uwaga: jeśli nie ma sposobu, aby zmodyfikować środowisko, aby zapobiec błędowi, może powinieneś użyć innego modułu
cwallenpoole
4

Umieść kod wewnątrz funkcji i nie będzie działał, dopóki nie wywołasz funkcji. Powinieneś mieć główną funkcję w swoim main.py. z oświadczeniem:

if __name__ == '__main__':
  main()

Następnie, jeśli zadzwonisz funkcja będzie działać. Jeśli importujesz , nie będzie. Dla jasności prawdopodobnie powinieneś zmienić nazwę na inną.python main.pymain()main.pymain.py

Matt
źródło
3

Pojawiła się propozycja rozszerzenia Pythona PEP 299, która miała na celu zastąpienie if __name__ == '__main__':idiomu def __main__:, ale została odrzucona. Wciąż dobrze jest wiedzieć, o czym należy pamiętać podczas używania if __name__ = '__main__':.

Paul Tobias
źródło
2

Możesz napisać swój „main.py” w ten sposób:

#!/usr/bin/env python

__all__=["somevar", "do_something"]

somevar=""

def do_something():
    pass #blahblah

if __name__=="__main__":
    do_something()
hgoldfish
źródło
-1

Chociaż nie możesz używać importbez uruchomienia kodu; istnieje dość szybki sposób wprowadzania zmiennych; przy użyciu numpy.savez, który przechowuje zmienne jako tablice numpy w pliku .npz. Następnie możesz załadować zmienne za pomocą numpy.load.

Zobacz pełny opis w dokumentacji Scipy

Należy pamiętać, że dotyczy to tylko zmiennych i tablic zmiennych, a nie metod itp.

user3569257
źródło
-4

Spróbuj po prostu zaimportować potrzebne funkcje z main.py? Więc,

from main import SomeFunction

Możliwe, że nazwałeś funkcję w batch.py ​​taką samą, jak w main.py, a podczas importu main.py program uruchamia funkcję main.py zamiast funkcji batch.py; wykonanie powyższego powinno to naprawić. Mam nadzieję.

Dave Lewis
źródło
Przynajmniej w systemie Windows tak nie jest.
Martín Coll
2
import mainNIE importuje wszystkiego z main do bieżącej przestrzeni nazw. Dodaje tylko jeden mainsymbol w bieżącej przestrzeni nazw, więc kolizje nie mogą wystąpić.
remram