Запустите скрипт Python из другого скрипта Python, передав аргументы

Я хочу запустить скрипт Python из другого скрипта Python. Я хочу передать переменные, как если бы я использовал командную строку.

Например, я запускаю свой первый скрипт, который будет перебирать список значений (0,1,2,3) и передавать их во второй скрипт script2.py 0 затем script2.py 1, так далее.

Я нашел SO 1186789, который является похожим вопросом, но ответ ars вызывает функцию, где, поскольку я хочу запустить весь сценарий, не просто функцию, а ответ Бальфы вызывает сценарий, но без аргументов. Я изменил это, как показано ниже, в качестве теста:

execfile("script2.py 1")

Но он не принимает переменные должным образом. Когда я распечатаю sys.argv в script2.py это исходный вызов команды для первого скрипта "['C:\script1.py'].

Я действительно не хочу менять оригинальный скрипт (то есть, script2.py в моем примере), так как он мне не принадлежит.

Я полагаю, что должен быть способ сделать это, я просто запутался, как ты это делаешь.

7 ответов

Решение

Попробуйте использовать os.system:

os.system("script2.py 1")

execfile отличается тем, что он предназначен для запуска последовательности операторов Python в текущем контексте выполнения. Вот почему sys.argv не изменился для вас.

В идеале, скрипт Python, который вы хотите запустить, будет настроен с таким кодом в конце:

def main(arg1, arg2, etc):
    # do whatever the script does


if __name__ == "__main__":
    main(sys.argv[1], sys.argv[2], sys.argv[3])

Другими словами, если модуль вызывается из командной строки, он анализирует параметры командной строки и затем вызывает другую функцию, main(), чтобы сделать реальную работу. (Фактические аргументы будут различаться, и анализ может быть более сложным.)

Если вы хотите вызвать такой скрипт из другого скрипта Python, вы можете просто import это и вызов modulename.main() напрямую, а не через операционную систему.

os.system будет работать, но это обходной (читай "медленный") способ сделать это, так как вы каждый раз запускаете совершенно новый процесс интерпретатора Python без изюминки.

Это по своей сути неправильно. Если вы запускаете скрипт Python из другого скрипта Python, вы должны общаться через Python, а не через ОС:

import script1

В идеальном мире вы сможете вызывать функцию внутри script1 непосредственно:

for i in range(whatever):
    script1.some_function(i)

При необходимости можно взломать sys.argv, Есть отличный способ сделать это, используя менеджер контекста, чтобы гарантировать, что вы не вносите постоянные изменения.

import contextlib
@contextlib.contextmanager
def redirect_argv(num):
    sys._argv = sys.argv[:]
    sys.argv=[str(num)]
    yield
    sys.argv = sys._argv

with redirect_argv(1):
    print(sys.argv)

Я думаю, что это предпочтительнее, чем передавать все ваши данные в ОС и обратно; это просто глупо.

Я думаю, что хорошая практика может быть что-то вроде этого;

import subprocess
cmd = 'python script.py'

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
out, err = p.communicate() 
result = out.split('\n')
for lin in result:
    if not lin.startswith('#'):
        print(lin)

согласно документации, модуль подпроцесса позволяет создавать новые процессы, подключаться к их каналам ввода / вывода / ошибок и получать их коды возврата. Этот модуль предназначен для замены нескольких старых модулей и функций:

os.system
os.spawn*
os.popen*
popen2.*
commands.*

Используйте связь () вместо.stdin.write, .stdout.read или.stderr.read, чтобы избежать взаимных блокировок из-за того, что другие буферы конвейера ОС заполняют и блокируют дочерний процесс. Читать здесь

Модуль SubProcess:
http://docs.python.org/dev/library/subprocess.html

import subprocess
subprocess.Popen("script2.py 1", shell=True)

При этом вы также можете перенаправить stdin, stdout и stderr.

import subprocess
subprocess.call(" python script2.py 1", shell=True)

Если os.system недостаточно мощная для вас, есть модуль подпроцесса.

Другие вопросы по тегам