【问题标题】:Controlling a python script from another script从另一个脚本控制 python 脚本
【发布时间】:2016-04-14 20:11:41
【问题描述】:

我正在尝试学习如何编写脚本control.py,该脚本在循环中运行另一个脚本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 脚本来控制另一个正在运行的脚本。 (例如,可以访问它打印的内容等等)。
  • 最后,是否有可能在新的终端中运行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 是这样的:(按照 Marc 的建议)

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

【问题讨论】:

  • os.system 已弃用;你应该使用subprocess 模块
  • 要在新终端中运行 test.py,您需要启动该进程,例如subprocess.call(["xterm", "-e", "python", "test.py", "someargument"])
  • 你可能对pexpect感兴趣。
  • @zondo 好样的!你能在这里展示一个例子吗?使用 pexpect

标签: python


【解决方案1】:

你可以使用 subprocess 模块,也可以使用 os.popen

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

打开与命令之间的管道。返回值是一个连接到管道的打开文件对象,可以根据模式是'r'(默认)还是'w'来读取或写入。

我建议使用子流程

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

或者subprocess.Popen -->类似于os.popen的(比如)

使用popen,您可以读取连接的对象/文件并检查“立即停止”是否存在。

os.system 没有被弃用,你也可以使用(但你不会从中得到对象),你可以在执行结束时检查是否返回。

从 subprocess.call 您可以在新终端中运行它,或者如果您只想多次调用 test.py --> 您可以将脚本放在 def main() 中并尽可能多地运行 main直到生成“立即停止”为止。

希望这能解决您的问题 :-) 否则再次发表评论。

看看你上面写的你也可以直接从操作系统调用将输出重定向到一个文件 --> os.system(test.py *args >> /tmp/mickey.txt) 然后你可以检查每个环绕文件。

如上所述,popen 是您可以访问的目标文件。

【讨论】:

  • 谢谢 Marco,我会尝试一个简单的脚本并尝试这个想法,我会尽快回复您
  • 您正在寻找的正是线程。这就是你最终需要的 :-) 我上面的建议更容易一些,但我猜线程是正确的答案 :-) 祝你有美好的一天。
  • 我在帖子中添加了第一次尝试。它可以做一些我想做的事情。仍然在新终端(在 ubuntu 上)中调用子进程,有什么想法吗?
  • 不确定创建标志是否会在 Popen 中帮助您解决这种特殊情况。创建标志=CREATE_NEW_CONSOLE。您还可以在此处查看子流程文档:docs.python.org/2/library/subprocess.html#subprocess.Popen 希望这对您有所帮助:-)
  • CREATE_NEW_CONSOLE 仅适用于我认为的 Windows,我正在运行 ubuntu
【解决方案2】:

您在对 Marc Cabos 的回答的评论中暗示的是 Threading

Python 可以通过多种方式使用其他文件的功能。如果test.py 的内容可以封装在一个函数或类中,那么您可以将import 的相关部分封装到您的程序中,让您可以更方便地访问该代码的运行。

如其他答案中所述,您可以使用脚本的标准输出,在子进程中运行它。这可以根据需要为您提供单独的终端输出。

但是,如果您想同时运行test.py 并在变量更改时访问它们,那么您需要考虑线程化。

【讨论】:

  • 哇,我学到了很多东西。实际上,在这个特定示例中,我只是尝试在此处访问 test.py 的打印输出。
  • 我在帖子中添加了一个失败的尝试,如果你想看看
【解决方案3】:

是的,您可以使用 Python 使用 stdin/stdout 控制另一个程序,但是当使用另一个进程输出时,通常会出现缓冲问题,换句话说,另一个进程在完成之前不会真正输出任何内容。

在某些情况下,输出是否被缓冲取决于程序是否从终端启动。

如果您是这两个程序的作者,那么最好使用另一个进程间通道,其中刷新由代码显式控制,例如套接字。

【讨论】:

  • 哦 :(( 真可惜……你有办法解决这个问题吗?(因为我只关心 test.py 打印的内容,而不关心它所做的其他事情,所以这就是为什么我认为如果我在另一个终端上运行它,然后也许我有机会阅读终端本身以了解test.py 正在打印什么)
【解决方案4】:

您可以为此使用“子流程”库。

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

【讨论】:

  • 您好,感谢您的建议。如果我没记错的话,只有在 p 完成后才会填写这个 answer, err ,对吗?我有点想在运行时读取子进程的打印,然后如果在打印中打印了“立即停止”,则停止该子进程。这可以实现吗?
  • 测试它是否正常工作...我现在无法检查它(只是编码)。
  • 非常感谢,现在就试试。我猜你的意思是在第二个条件之后写break,对吧?
  • 如果我有多个子进程,例如p,p2,p3,我如何制作你建议的while循环,但专门针对进程p,我问是因为你只是写了while True:,但现在手头有多个,我想做除了进程p之外的相同循环,所以像while p==True: 这样的东西不起作用
猜你喜欢
  • 2017-03-30
  • 2011-03-04
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-21
  • 1970-01-01
相关资源
最近更新 更多