Управление python script из другого script

Я пытаюсь научиться писать script control.py, который запускает еще один script test.py в цикле определенное количество раз, в каждом прогоне читает его вывод и останавливает его, если некоторые печатается предопределенный вывод (например, текст "останавливается сейчас" ), и цикл продолжает свою итерацию (один раз test.py закончил, либо самостоятельно, либо силой). Итак, что-то вроде строк:

for i in range(n):
    os.system('test.py someargument')
    if output == 'stop now': #stop the current test.py process and continue with next iteration
    #output here is supposed to contain what test.py prints
  • Проблема с вышеизложенным заключается в том, что он не проверяет вывод test.py по мере его запуска, а ожидает, что процесс test.py завершится сам по себе, правильно?
  • В основном пытается узнать, как я могу использовать python script для управления другим, когда он запущен. (например, доступ к тому, что он печатает и т.д.).
  • Наконец, можно ли запустить test.py в новом терминале (т.е. не в терминале control.py) и все еще достичь вышеуказанных целей?

Попытка: test.py:

from itertools import permutations
import random as random


perms = [''.join(p) for p in permutations('stop')]

for i in range(1000000):
    rand_ind = random.randrange(0,len(perms))
    print perms[rand_ind]

И control.py: (следуя предложению Марка)

import subprocess

command = ["python", "test.py"]
n = 10
for i in range(n):
    p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while True:
        output = p.stdout.readline().strip()
        print output
        #if output == '' and p.poll() is not None:
        #    break
        if output == 'stop':
            print 'sucess'
            p.kill()
            break
            #Do whatever you want
    #rc = p.poll() #Exit Code

Ответ 1

То, что вы намекаете в своем комментарии к ответу Марка Кабоса, Threading

Существует несколько способов использования Python для работы с другими файлами. Если содержимое test.py может быть инкапсулировано в функцию или класс, то вы можете import соответствующие части в вашу программу, предоставляя вам больший доступ к записям этого кода.

Как описано в других ответах, вы можете использовать stdout script, запуская его в подпроцессе. Это может привести к раздельному выходу на терминал.

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

Ответ 2

Вы можете использовать модуль подпроцесса, а также os.popen

os.popen(command[, mode[, bufsize]])

Откройте трубу в команде или из нее. Возвращаемое значение - это объект открытого файла, подключенный к каналу, который может быть прочитан или записан в зависимости от того, является ли режим "r" (по умолчанию) или "w".

В подпроцессе я предлагаю

subprocess.call(['python.exe', command])

или подпроцесс .Popen → , который похож на os.popen(например)

С помощью popen вы можете прочитать подключенный объект/файл и проверить, есть ли там "Stop now".

Система os.system не устарела, и вы также можете использовать ее (но вы не получите от нее объект), вы можете просто проверить, вернется ли возврат в конце выполнения.

Из subprocess.call вы можете запустить его в новом терминале или если вы хотите вызывать несколько раз ТОЛЬКО test.py → , чем вы можете поместить свой script в def main() и запустить main как так как вы хотите, пока не появится "Stop now".

Надеюсь, что это разрешит ваш запрос:-) иначе комментарий еще раз.

Глядя на то, что вы написали выше, вы также можете перенаправить вывод в файл непосредственно из вызова ОС → os.system(test.py * args → /tmp/mickey.txt), тогда вы можете проверить каждый вокруг файла.

Как сказано, popen - это объектный файл, доступ к которому вы можете получить.

Ответ 3

Для этого вы можете использовать библиотеку "subprocess".

import subprocess

command = ["python", "test.py", "someargument"]

for i in range(n):
    p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while True:
        output = p.stdout.readline()
        if output == '' and p.poll() is not None:
            break
        if output == 'stop now':
            #Do whatever you want
    rc = p.poll() #Exit Code

Ответ 4

Да, вы можете использовать Python для управления другой программой с помощью stdin/stdout, но при использовании другого выходного процесса часто возникает проблема буферизации, другими словами, другой процесс на самом деле ничего не выводит, пока это не будет сделано.

Есть даже случаи, когда вывод буферизуется или не зависит от того, запущена ли программа с терминала или нет.

Если вы являетесь автором обеих программ, то, вероятно, лучше использовать другой канал interprocess, где промывка явно управляется кодом, например сокетами.