В Python я могу вызвать main() импортированного модуля?
В Python у меня есть модуль myModule.py, где я определяю несколько функций и main(), что требует нескольких аргументов командной строки.
Обычно я называю это main() от bash script. Теперь я хотел бы поместить все в небольшой пакет, поэтому я подумал, что, возможно, я могу превратить свой простой bash script в Python script и поместить его в пакет.
Итак, как мне на самом деле вызвать функцию main() myModule.py из функции main() MyFormerBashScript.py? Могу ли я это сделать? Как передать любые аргументы на него?
Ответы
Ответ 1
Это просто функция. Импортируйте его и назовите его:
import myModule
myModule.main()
Если вам нужно проанализировать аргументы, у вас есть два варианта:
-
Разделите их в main()
, но передайте sys.argv
в качестве параметра (весь код ниже в том же модуле myModule
):
def main(args):
# parse arguments using optparse or argparse or what have you
if __name__ == '__main__':
import sys
main(sys.argv[1:])
Теперь вы можете импортировать и вызывать myModule.main(['arg1', 'arg2', 'arg3'])
из другого другого модуля.
-
Иметь main()
принимать параметры, которые уже разобраны (снова весь код в модуле myModule
):
def main(foo, bar, baz='spam'):
# run with already parsed arguments
if __name__ == '__main__':
import sys
# parse sys.argv[1:] using optparse or argparse or what have you
main(foovalue, barvalue, **dictofoptions)
и импортировать и вызывать myModule.main(foovalue, barvalue, baz='ham')
в другом месте и передавать аргументы python по мере необходимости.
Трюк здесь заключается в том, чтобы определить, когда ваш модуль используется как script; когда вы запускаете файл python в качестве основного оператора script (python filename.py
) no import
, поэтому python вызывает этот модуль "__main__"
. Но если этот же код filename.py
обрабатывается как модуль (import filename
), тогда python использует это вместо имени модуля. В обоих случаях устанавливается переменная __name__
, и тестирование на это указывает вам, как был выполнен ваш код.
Ответ 2
Это зависит. Если основной код защищен if
, как в:
if __name__ == '__main__':
...main code...
то нет, вы не можете заставить Python выполнить это, потому что вы не можете влиять на автоматическую переменную __name__
.
Но когда весь код находится в функции, он может быть способен. Попробуйте
import myModule
myModule.main()
Это работает, даже если модуль защищает себя с помощью __all__
.
from myModule import *
может не сделать main
видимым для вас, поэтому вам действительно нужно импортировать сам модуль.
Ответ 3
Ответ Martijen имеет смысл, но в нем отсутствует нечто важное, что может показаться очевидным для других, но мне было трудно понять.
В версии, где вы используете argparse, вам нужно иметь эту строку в основном теле.
args = parser.parse_args(args)
Обычно, когда вы используете argparse только в script, вы просто пишете
args = parser.parse_args()
и parse_args найти аргументы из командной строки. Но в этом случае основная функция не имеет доступа к аргументам командной строки, поэтому вы должны сказать argparse, что аргументы.
Вот пример
import argparse
import sys
def x(x_center, y_center):
print "X center:", x_center
print "Y center:", y_center
def main(args):
parser = argparse.ArgumentParser(description="Do something.")
parser.add_argument("-x", "--xcenter", type=float, default= 2, required=False)
parser.add_argument("-y", "--ycenter", type=float, default= 4, required=False)
args = parser.parse_args(args)
x(args.xcenter, args.ycenter)
if __name__ == '__main__':
main(sys.argv[1:])
Предполагая, что вы назвали это mytest.py
Чтобы запустить его, вы можете либо выполнить любую из них из командной строки
python ./mytest.py -x 8
python ./mytest.py -x 8 -y 2
python ./mytest.py
который возвращает соответственно
X center: 8.0
Y center: 4
или
X center: 8.0
Y center: 2.0
или
X center: 2
Y center: 4
Или, если вы хотите запустить с другого python script, вы можете сделать
import mytest
mytest.main(["-x","7","-y","6"])
который возвращает
X center: 7.0
Y center: 6.0
Ответ 4
Мне тоже нужно было использовать argparse
.
Вещь parse_args
функция экземпляра объекта argparse.ArgumentParser
неявно принимает свои аргументы по умолчанию от sys.args
. Работа вокруг, следуя линии Martijn, состоит в том, чтобы сделать это явным, поэтому вы можете изменить аргументы, которые вы передаете на parse_args
как желание.
def main(args):
# some stuff
parser = argparse.ArgumentParser()
# some other stuff
parsed_args = parser.parse_args(args)
# more stuff with the args
if __name__ == '__main__':
import sys
main(sys.argv[1:])
Ключевым моментом является передача аргументов функции parse_args
.
Позже, чтобы использовать главное, вы просто делаете, как говорит Мартинн.
Ответ 5
Предполагая, что вы также пытаетесь передать аргументы командной строки.
import sys
import myModule
def main():
# this will just pass all of the system arguments as is
myModule.main(*sys.argv)
# all the argv but the script name
myModule.main(*sys.argv[1:])
Ответ 6
Ответ, который я искал, ответил здесь: Как использовать python argparse с аргументами, отличными от sys.argv?
Если main.py
и parse_args()
записаны таким образом, тогда синтаксический анализ может быть выполнен красиво
# main.py
import argparse
def parse_args():
parser = argparse.ArgumentParser(description="")
parser.add_argument('--input', default='my_input.txt')
return parser
def main(args):
print(args.input)
if __name__ == "__main__":
parser = parse_args()
args = parser.parse_args()
main(args)
Затем вы можете вызвать main()
и проанализировать аргументы с помощью parser.parse_args(['--input', 'foobar.txt'])
к нему в другом python script:
# temp.py
from main import main, parse_args
parser = parse_args()
args = parser.parse_args([]) # note the square bracket
# to overwrite default, use parser.parse_args(['--input', 'foobar.txt'])
print(args) # Namespace(input='my_input.txt')
main(args)