【问题标题】:Sending to the stdin of a program in python3在 python3 中发送到程序的标准输入
【发布时间】:2016-06-01 05:51:24
【问题描述】:

我必须要文件,ma​​in.pychild.py

我正在尝试向 ma​​in.py 的标准输入发送一个字符串。

这是我不完整的代码:

main.py

from subprocess import *
import time

def main():
    program = Popen(['python.exe'. 'child.py', 'start'])
    while True: #waiting for'1' to be sent to the stdin
        if sys.stdin == '1':
            print('text)

if __name__ == '__main__':
    main()

child.py

import sys

if sys.argv[1] == 'start':
    inp = input('Do you want to send the argument?\n').lower()
    if inp == 'no':
        sys.exit()
    elif inp == 'yes':
        #Somehow send '1' to the stdin of 1.py while it is running

我不知道该怎么做。

我正在使用 python 3.5.1 运行 Windows 10

-谢谢

编辑: 当我将参数发送回 main.py 时,我无法重新打开程序。 os.system 重新打开对我来说没用的程序。

这些程序是我正在尝试做的一个小演示。在我的实际程序中,我无法做到这一点,因为这两个程序正在相互“交流”,需要始终打开。

我需要回答的是一种向 main.py 发送参数的方法,可能使用标准输入,但是当我发送参数时,它无法重新打开程序。像 os.system 这样的一些例子重新打开程序,这不是我想要做的。我需要一直打开 main.py。

我的新当前代码不起作用。弹出一个窗口,然后关闭。

main.py

from subprocess import Popen, PIPE, STDOUT
x = Popen(['python.exe', '2.py', 'start'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
while x.poll() is None:
    if b'Do you want to send the argument?' in x.stdout.read():
        x.stdin.write(b'yes\n')

child.py

import sys
import time
time.sleep(1)
if 1 = 1:
    inp = input('Do you want to send the argument?\n').lower()
    if inp == 'no':
        sys.exit()
    elif inp == 'yes':
        sys.stdout.write('1')
        sys.stdout.flush()

这是我的代码。

【问题讨论】:

  • 为什么不直接做import child
  • 一般问题:您为什么要这样做?上下文是什么?
  • @VikasMadhusudana 不,不是:Popen 已经在这里做到了。这是关于将标准输出传递给另一个程序的标准输入(在这种情况下是父程序),在 *nix 语法中是与 shell 相关的,而不是真正的 Python。
  • 我使用这个程序的方式,我不能只导入孩子。 @Torxed
  • main.py 和 child.py 的样子,是的,你可以,因为 child 会从父级继承 sys.argv,还有其他方法可以使用自定义参数和全局变量进行常规 python 导入。

标签: python python-3.x stdin


【解决方案1】:

你需要的是类似(main.py):

from subprocess import Popen, PIPE, STDOUT
x = Popen(['some_child.exe', 'parameter'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)

while x.poll() is None:
    child_output = x.stdout.readline()
    print(child_output)
    if b'Do you want to send the argument?' in child_output:
        x.stdin.write(b'yes\n')
        x.stdin.flush()
x.stdout.close()
x.stdin.close()

您假设 child.exe(在您的模型演示中,python.exe)通过 sys.stdin/stdoutmain.py 通信,但是这些 I/O 用于与生成该进程的 shell 通信。

就像孩子stdout/stdin 将与产生该进程的shell 进行通信,在本例中为Popen()

subprocess.Popen(...) 的每个生成的子进程都将与它自己的stdout/stdin/stderr 隔离,否则每个子进程都会把你的主进程 stdout/stdin 弄得一团糟。这意味着您必须检查该特定子进程的输出并相应地写入它,如上述示例中所做的那样。

一种看待它的方式是:

您正在启动main.py,并通过sys.stdoutsys.stdin 与它通信。 main.py 中的每个 input() 都会向 sys.stdout 输出一些内容,以便您阅读。

完全相同的逻辑适用于child.exe,其中每个input() 都会向sys.stdout 输出一些内容(- 但请记住-sys 不是跨进程的共享变量)

import sys

if sys.argv[1] == 'start':
    inp = input('Do you want to send the argument?\n').lower()
    if inp == 'no':
        sys.exit()
    elif inp == 'yes':
        #Somehow send '1' to the stdin of 1.py while it is running
        sys.stdout.write('1')
        sys.stdout.flush()

但是一个简单的print(1) 会做同样的事情,因为它基本上会为您输出1sys.stdout

2018 年编辑:不要忘记关闭您的输入和输出,因为它们可能会在您的文件系统上留下打开的文件描述符,占用资源并在以后的生活中造成问题。

其他信息传递者

假设您可以控制child.exe 的代码,并且可以以任何方式修改通信管道,其他一些选项是:

更多警示性的尾巴!

  • .readline() 将假定您的数据中某处有一个\n,很可能在最后。我切换到.readline() 有两个原因,.read() 将挂起并等待EOF,除非您确切指定要读取多少字节,如果我没有骑自行车的话。为了能够读取各种输出,您需要将select.select() 合并到您的代码中 - 或某种类型的缓冲区,您可以在其中调用x.stdout.read(1) 一次读取一个字节。因为如果您尝试读取 .read(1024) 并且缓冲区中没有 1024 个字节,您的读取将挂起,直到有 1024 个字符。

  • 我故意在你的 child.py 代码中留下了一个错误(我的作品) - 这是简单而基本的 Python - 希望这是关于如何调试错误的学习经验(你提到你不擅长它,这是一种学习方式)。

【讨论】:

  • 好的,我明白你的意思。你能举一个使用标准输出的例子吗? @Torxed
  • @nic 我的答案顶部有一个例子吗?这并不完美,因为我正在手机上编码。我可以在一秒钟内完善代码。
  • 好的,你能举出两个文件代码的例子吗?我说另一个例子的原因是因为 child.py 没有变量“x”,因为它没有 main.py 作为变量“x”打开。谢谢
  • @SilentMonk 取决于在这种情况下缓冲的含义。是的,如果你不清空x.stdout 的缓冲区,缓冲会挂起进程——因为清空IO 缓冲区非常重要。
  • @SilentMonk 是的,如果完整输出不完整但实际上在中途分割,我的 if 语句将无法捕获预期的输出。保持简单,因为 OP 已经对 IO 感到困惑。应该提一下。
猜你喜欢
  • 1970-01-01
  • 2014-03-04
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 2022-08-14
  • 2016-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多