Чому Python працює під час імпорту мого модуля і як його зупинити?


173

У мене є програма Python, яку я будую, яку можна запустити будь-яким з двох способів: перший - викликати "python main.py", який дружньо спонукає користувача до введення, а потім запускає введення користувача через програму. Інший спосіб - викликати "python batch.py -file- ", який передасть усі дружні вхідні дані і за один раз запустить цілий файл, який варто вводити через програму.

Проблема полягає в тому, що коли я запускаю "batch.py", він імпортує деякі змінні / методи / тощо з "main.py", і коли він запускає цей код:

import main

у першому рядку програми він негайно помиляється, оскільки намагається запустити код у "main.py".

Як я можу зупинити Python від запуску коду, що міститься в "головному" модулі, який я імпортую?

Відповіді:


251

Тому що саме так працює Python - ключові слова, такі як classі неdef є деклараціями . Натомість це реальні реальні заяви, які виконуються. Якби вони не були виконані, ваш модуль був би .. порожнім :-)

У будь-якому випадку, ідіоматичний підхід такий:

# 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()

Дивіться, що if __name__ == "__main__"для чого?

importОднак він вимагає контролю джерела над модулем, що редагується.

Щасливе кодування.


1
просто для підтвердження, ваш коментар "матеріал, який потрібно запускати лише тоді, коли не викликається через" імпорт "тут", має на увазі команди, які слід записати під main (), правда? Або це не має значення ??
Goldname

@Goldname Код всередині оператора if не буде запущений при імпорті, але основна функція сама по собі визначена і готова до використання навіть через імпорт. Цей модуль буде просто виконувати основну функцію під час запуску, а не виконувати її при імпорті. Все залежить від того, що ви хочете зробити. Якщо вам не потрібні команди всередині головного в іншому місці, обов'язково запишіть їх всередині if. Але для мене це виглядає акуратніше.
Фелікс

51

Завдяки тому, як працює Python, йому потрібно запускати ваші модулі, коли він імпортує їх.

Щоб запобігти виконанню коду в модулі при імпорті, але лише при безпосередньому запуску, ви можете захистити його таким чином if:

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

Ви можете поставити цей код main()методом, щоб ви могли або виконати файл безпосередньо, або імпортувати модуль і викликати main(). Наприклад, припустимо, що це у файлі foo.py.

def main():
    print "Hello World"

if __name__ == "__main__":
    main()

Цю програму можна запустити, перейшовши python foo.pyабо з іншого сценарію Python:

import foo

...

foo.main()

12

Використовувати if __name__ == '__main__'ідіому - __name__це спеціальна змінна, значення якої становить, '__main__'якщо модуль запускається як сценарій, а назва модуля, якщо він імпортується. Отже, ви зробили б щось подібне

# imports
# class/function definitions
if __name__ == '__main__':
    # code here will only run when you invoke 'python main.py'

4

На жаль, ви цього не робите. Це частина того, як працює синтаксис імпорту, і важливо, щоб він це defробив - пам’ятайте , що насправді щось виконується, якби Python не виконав імпорт, ви були б, ну, застрягли без функцій.

Оскільки ви, мабуть, маєте доступ до файлу, можливо, ви зможете подивитися і побачити, що викликає помилку. Можливо, можливо змінити ваше оточення, щоб запобігти виникненню помилки.


1
Як зауваження: якщо немає можливості змінити середовище, щоб помилку можна було запобігти, можливо, вам слід скористатися іншим модулем
cwallenpoole

4

Помістіть код всередині функції, і він не запуститься, поки ви не зателефонуєте до функції. Ви повинні мати головну функцію у своєму main.py. із заявою:

if __name__ == '__main__':
  main()

Потім, якщо ви телефонуєте функція буде працювати. Якщо ви імпортуєте , це не буде. Крім того, вам, мабуть, для чіткості слід перейменувати щось інше.python main.pymain()main.pymain.py


3

Була пропозиція щодо вдосконалення Python PEP 299, яка мала на меті замінити if __name__ == '__main__':ідіому def __main__:, але її відхилили. Це все-таки добре прочитати, щоб знати, що потрібно пам’ятати при використанні if __name__ = '__main__':.


2

Ви можете написати "main.py" так:

#!/usr/bin/env python

__all__=["somevar", "do_something"]

somevar=""

def do_something():
    pass #blahblah

if __name__=="__main__":
    do_something()

-1

Хоча ви не можете використовувати importбез запуску коду; є досить швидкий спосіб, коли ви можете вводити свої змінні; за допомогою використання numpy.savez, яке зберігає змінні як numpy масиви у файлі .npz. Після цього ви можете завантажити змінні за допомогою numpy.load.

Повний опис дивіться в документації на scipy

Зверніть увагу, це стосується лише змінних та масивів змінної, а не методів тощо.


-4

Спробуйте просто імпортувати функції, необхідні з main.py? Так,

from main import SomeFunction

Можливо, ви назвали функцію в batch.py ​​такою ж, як і в main.py, а коли ви імпортуєте main.py, програма замість функції batch.py ​​запускає функцію main.py; виконувати вище, слід це виправити. Я сподіваюсь.


Принаймні, у Windows це не так.
Мартін Колл

2
import mainНЕ імпортує все з головного в поточну область імен. Він додає лише один mainсимвол у поточну область імен, тому зіткнення не може відбутися.
ремрам
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.