Почему Python запускает мой модуль, когда я импортирую его, и как мне его остановить?

173

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

Проблема в том, что когда я запускаю «batch.py», он импортирует некоторые переменные / методы / и т. Д. Из «main.py», и когда он запускает этот код:

import main

в первой строке программы он сразу же выдает ошибку, потому что пытается запустить код в «main.py».

Как я могу остановить запуск Python кода, содержащегося в «основном» модуле, который я импортирую?

Dasmowenator
источник

Ответы:

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
просто чтобы подтвердить, ваш комментарий "вещи, которые запускаются, когда не вызывается через 'import' здесь", подразумевает команды, которые будут написаны в main (), верно? Или это не имеет значения ??
Goldname
@Goldname Код внутри оператора if не будет выполняться при импорте, но основная функция сама по себе определена и готова к использованию даже при импорте. Этот модуль будет просто выполнять основную функцию при запуске, а не выполнять ее при импорте. Все зависит от того, что вы хотите сделать. Если вам не нужны команды внутри main в другом месте, непременно напишите их в 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 не выполнял импорт, вы бы застряли без функций.

Так как у вас, вероятно, есть доступ к файлу, вы можете посмотреть, что является причиной ошибки. Может быть возможно изменить вашу среду, чтобы предотвратить возникновение ошибки.

cwallenpoole
источник
1
Как примечание: если нет способа изменить среду, чтобы предотвратить ошибку, возможно, вам следует использовать другой модуль
cwallenpoole
4

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

if __name__ == '__main__':
  main()

Затем, если вы звоните функция будет работать. Если вы импортируете , это не будет. Кроме того, вы должны, вероятно, переименовать что-то еще для ясности.python main.pymain()main.pymain.py

Matt
источник
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()
hgoldfish
источник
-1

Хотя вы не можете использовать importбез запуска кода; есть довольно быстрый способ ввода переменных; с помощью numpy.savezкоторого переменные хранятся в виде пустых массивов в файле .npz. После этого вы можете загрузить переменные, используя numpy.load.

Смотрите полное описание в документации Scipy

Обратите внимание, что это касается только переменных и массивов переменных, а не методов и т. Д.

user3569257
источник
-4

Попробуйте просто импортировать нужные функции из main.py? Так,

from main import SomeFunction

Возможно, вы назвали функцию в batch.py ​​так же, как в main.py, и при импорте main.py программа запускает функцию main.py вместо функции batch.py; выполнение вышеизложенного должно исправить это. Я надеюсь.

Дэйв Льюис
источник
По крайней мере, в Windows это не так.
Мартин Колл
2
import mainНЕ импортирует все из main в текущее пространство имен. Он добавляет только один mainсимвол в текущем пространстве имен, поэтому столкновения не могут произойти.
Ремрам