Как лучше всего вызвать скрипт из другого скрипта?

У меня есть скрипт с именем 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, чтобы поместить весь его код в подпрограмму.

Документация: Python 2, Python 3

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)
Другие вопросы по тегам