【问题标题】:How to interact with an external program in Python 3?如何在 Python 3 中与外部程序交互?
【发布时间】:2020-05-22 13:38:01
【问题描述】:

使用 Python 3,我想执行一个外部程序,通过在标准输入中提供一些文本与它进行交互,然后打印结果。

例如,我创建了以下外部程序,名为test.py

print('Test Program')
print('1 First option, 2 Second Option')

choice = input()

if choice == '1':
    second_param = input('Insert second param: ')
    result = choice + ' ' + second_param
        
    print(result)

如果我直接运行这个程序,它会按预期工作。如果我提供输入1,然后提供2,则结果为1 2

我想在另一个脚本中运行这个程序并与之交互以打印相同的结果。

在阅读了subprocess 的文档并查看了关于 SO 的类似问题后,我得到了以下结果:

EXTERNAL_PROG = 'test.py'

p = Popen(['py', EXTERNAL_PROG], stdout=PIPE, stdin=PIPE, shell=True)

print(p.stdout.readline().decode('utf-8'))
print(p.stdout.readline().decode('utf-8'))
p.stdin.write(b'1\n')
p.stdin.write(b'2\n')
print(p.stdout.readline().decode('utf-8'))

但是,当我运行代码时,程序在打印1 First option, 2 Second Option 后冻结,我需要重新启动我的 shell。这可能是因为subprocess.stdout.readline() 期望找到一个换行符,而第二个参数的提示符不包含一个。


我发现 2 个 SO 问题讨论了类似的问题,但我无法让它发挥作用。

Here,答案推荐使用pexpect模块。我尝试使代码适应我的情况,但没有奏效。

Here,建议使用-u,但添加并没有改变。


我知道可以通过修改test.py 找到解决方案,但在我的情况下这是不可能的,因为我需要使用另一个外部程序,这只是一个基于它的最小示例。

【问题讨论】:

  • 尝试将p.stdin.readline() 命令更改为p.stdin.read()。你甚至可能想把它放在一个循环中,比如while (print(p.stdin.read())): next ,以确保任何需要阅读的东西都能被阅读。不确定这是否是问题所在,但它将测试您关于 readline() 功能的理论。

标签: python python-3.x subprocess


【解决方案1】:

如果您的程序有固定输入(意味着输入在运行时不会改变),那么这个解决方案可能是相关的。

回答

首先创建文件。

  • 输入文件。将其命名为 input.txt 并将1 2 放入其中

command = "python test.py < input.txt > output.txt 2>&1"

# now run this command

os.system(command)

当你运行它时,你会在同一目录中找到output.txt。如果您的程序成功执行,则output.txt 包含代码test.py 的输出,但如果您的代码出现任何错误,则错误在output.txt 中。

随心所欲地回答

main.py变成

import sys
from subprocess import PIPE, Popen

EXTERNAL_PROG = 'test.py'

p = Popen(['python3', EXTERNAL_PROG], stdout=PIPE, stdin=PIPE, stderr=PIPE)

print(p.stdout.readline())
print(p.stdout.readline())
p.stdin.write(b'1\n')
p.stdin.write(b'2\n')
p.stdin.flush()
print(p.stdout.readline())
print(p.stdout.readline())

【讨论】:

  • 如果我在input.txt 中有1\n2,则此方法有效。如果输入是固定的,这是一个很好的解决方案。
  • 是的,因为您的程序分别读取 2 个整数。您的输入文件包含您通过控制台提供给程序的相同数据。如果您得到了预期的结果,请接受答案
  • 这个答案的唯一问题是我不想将我的输入放在文件中。我想通过程序本身传递它。假设我有firstParam = 1secondParam = 2。有没有办法将其用作输入而不是从input.txt 读取?
  • 如果您的输入是静态的(不改变运行时),那么您可以将其写入文件,然后运行上面的代码,但如果您的输入正在改变,那么它根本就没有用。
  • 假设我有firstParamsecondParam 作为变量,我已经计算了它们的值。我可以将它们的值保存到文件中,运行您的代码,然后删除该文件。但是有没有更好的方法来做到这一点,也许使用不同的command
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-21
  • 2014-03-13
  • 1970-01-01
  • 2020-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多