Как лучше всего вызвать скрипт из другого скрипта?
У меня есть скрипт с именем test1.py, которого нет в модуле. Он просто имеет код, который должен выполняться при запуске самого скрипта. Там нет функций, классов, методов и т. Д. У меня есть другой скрипт, который работает как служба. Я хочу вызвать test1.py из скрипта, работающего как сервис.
Например:
Файл test1.py
print "I am a test"
print "see! I do nothing productive."
Файл service.py
# Lots of stuff here
test1.py # do whatever is in test1.py
Я знаю об одном методе, который открывает файл, читает содержимое и в основном оценивает его. Я предполагаю, что есть лучший способ сделать это. Или, по крайней мере, я на это надеюсь.
18 ответов
Обычный способ сделать это что-то вроде следующего.
test1.py
def some_func():
print 'in test 1, unproductive'
if __name__ == '__main__':
# test1.py executed as script
# do something
some_func()
service.py
import test1
def service_func():
print 'service func'
if __name__ == '__main__':
# service.py executed as script
# do something
service_func()
test1.some_func()
Это возможно в Python 2, используя
execfile("test2.py")
См. Документацию для обработки пространств имен, если это важно в вашем случае.
Тем не менее, вы должны рассмотреть возможность использования другого подхода; ваша идея (из того, что я вижу) не выглядит очень чистой.
По-другому:
Файл test1.py:
print "test1.py"
Файл service.py:
import subprocess
subprocess.call("test1.py", shell=True)
Преимущество этого метода в том, что вам не нужно редактировать существующий скрипт Python, чтобы поместить весь его код в подпрограмму.
import os
os.system("python myOtherScript.py arg1 arg2 arg3")
Используя ОС вы можете совершать звонки прямо на ваш терминал. Если вы хотите быть еще более конкретным, вы можете объединить вашу входную строку с локальными переменными, т.е.
command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2]
os.system(command)
Если вы хотите, чтобы test1.py оставался исполняемым с той же функциональностью, что и при вызове внутри service.py, сделайте что-то вроде:
test1.py
def main():
print "I am a test"
print "see! I do nothing productive."
if __name__ == "__main__":
main()
service.py
import test1
# lots of stuff here
test1.main() # do whatever is in test1.py
Я предпочитаю беглый:
#!/usr/bin/env python
# coding: utf-8
import runpy
runpy.run_path(path_name='script-01.py')
runpy.run_path(path_name='script-02.py')
runpy.run_path(path_name='script-03.py')
Вы не должны делать это. Вместо этого сделайте:
test1.py:
def print_test():
print "I am a test"
print "see! I do nothing productive."
service.py
#near the top
from test1 import print_test
#lots of stuff here
print_test()
Использование import test1
для 1-го использования - он выполнит скрипт. Для последующих вызовов обработайте скрипт как импортированный модуль и вызовите reload(test1)
метод.
когда
reload(module)
выполняется:
- Код модулей Python перекомпилируется, и код уровня модуля повторно выполняется, определяя новый набор объектов, которые связаны с именами в словаре модуля. Функция init модулей расширения не вызывается
Простая проверка sys.modules
может использоваться для вызова соответствующего действия. Продолжать ссылаться на имя скрипта в виде строки ('test1'
), используйте встроенную функцию import ().
import sys
if sys.modules.has_key['test1']:
reload(sys.modules['test1'])
else:
__import__('test1')
Как уже упоминалось, runpy
- хороший способ запускать другие скрипты или модули из текущего скрипта.
Кстати, трассировщик или отладчик довольно часто это делают, и в таких обстоятельствах такие методы, как импорт файла напрямую или запуск файла в подпроцессе, обычно не работают.
Это также требует внимания при использовании exec
запустить код. Вы должны предоставить надлежащиеrun_globals
чтобы избежать ошибки импорта или некоторых других проблем. Ссылаться наrunpy._run_code
для подробностей.
Пример использования подпроцесса.
from subprocess import run
import sys
run([sys.executable, 'fullpathofyourfile.py'])
Почему бы просто не импортировать test1? Каждый скрипт Python является модулем. Лучшим способом было бы иметь функцию, например, main/run в test1.py, импортировать test1 и запустить test1.main(). Или вы можете выполнить test1.py как подпроцесс.
Я нашел стандартную библиотеку наиболее удобной. Почему? Вы должны учитывать случай, когда ошибка возникает в скрипте, и вы можете справиться с этим в коде. И текст трассировки (для записи ошибки в файл журнала для дальнейшего изучения), и объект ошибки (для обработки ошибки в зависимости от ее типа): когда с
subprocess
библиотека, из которой я не смог продвигать объект ошибки в
service.py
, только вывод трассировки. Кроме того, по сравнению с решением «импортировать test1.py как модуль»,
runpy
лучше, потому что вам не нужно обертывать код
test1.py
в
def main():
функция.
Например, кусок кода с
traceback
модуль для перехвата последнего текста ошибки:
import traceback
import runpy #https://www.tutorialspoint.com/locating-and-executing-python-modules-runpy
from datetime import datetime
try:
runpy.run_path("./E4P_PPP_2.py")
except Exception as e:
print("Error occurred during execution at " + str(datetime.now().date()) + " {}".format(datetime.now().time()))
print(traceback.format_exc())
print(e)
Добавьте это в свой скрипт python.
import os
os.system("exec /path/to/another/script")
Эта команда выполняет эту команду, как если бы она была введена в оболочку.
Это пример с subprocess
библиотека:
import subprocess
python_version = '3'
path_to_run = './'
py_name = '__main__.py'
# args = [f"python{python_version}", f"{path_to_run}{py_name}"] # Avaible in python3
args = ["python{}".format(python_version), "{}{}".format(path_to_run, py_name)]
res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()
if not error_:
print(output)
else:
print(error_)
Этот процесс несколько неортодоксален, но будет работать во всех версиях Python,
Предположим, вы хотите выполнить скрипт с именем "рекомендует.py" внутри условия "если", затем используйте,
if condition:
import recommend
Техника другая, но работает!
Согласно приведенному примеру, это лучший способ:
# test1.py
def foo():
print("hellow")
# test2.py
from test1 import foo # might be different if in different folder.
foo()
Но, судя по названию, использование
os.startfile("path")
это лучший способ, так как он маленький и работает. Это выполнит указанный файл. Моя версия Python 3.x +.
Как я это обнаружил, когда искал решение в Python 3 . В Python 3 вы можете просто использоватьimport
функции (обратите внимание, что py.files не должен иметь имя библиотеки, оно должно иметь уникальное имя):
Файл test1.py:
print "I am a test"
print "see! I do nothing productive."
Файл service.py:
import test1
и если вы запустите толькоservice.py
он сгенерирует вывод:
"I am a test"
"see! I do nothing productive."
Обратите внимание, что он должен находиться в том же репозитории/папке.
Я нашел этот простой пример на http://hplgit.github.io/primer.html/doc/pub/tech/._tech-solarized012.html для вызова одного скрипта Python из другого, даже если вам нужно указать несколько аргументов
import subprocess
cmd = 'python train_frcnn.py --input_weight_path model_frcnn.hdf5 -o simple -p take2.csv'
subprocess.call(cmd, shell=True)