【问题标题】:Unable to write to stdin in subprocess无法在子进程中写入标准输入
【发布时间】:2013-06-24 03:46:53
【问题描述】:

我无法在 python 3.2.5 中将命令传递给标准输入。我尝试了以下两种方法 另外:这个问题是previous question 的延续。

from subprocess import Popen, PIPE, STDOUT
import time

p = Popen([r'fileLoc/uploader.exe'],shell = True, stdout=PIPE, stdin=PIPE, stderr=STDOUT)
p.stdin.write('uploader -i file.txt -d outputFolder\n')
print (p.communicate()[0])
p.stdin.close()

当我在 IDLE 解释器中尝试代码时,我还会收到诸如 96、0、85 之类的数字,以及来自print (p.communicate()[0]) 之类的错误

Traceback (most recent call last):
  File "<pyshell#132>", line 1, in <module>
    p.communicate()[0]
  File "C:\Python32\lib\subprocess.py", line 832, in communicate
    return self._communicate(input)
  File "C:\Python32\lib\subprocess.py", line 1060, in _communicate
    self.stdin.close()
IOError: [Errno 22] Invalid argument

我也用过:

from subprocess import Popen, PIPE, STDOUT
    import time

    p = Popen([r'fileLoc/uploader.exe'],shell = True, stdout=PIPE, stdin=PIPE, stderr=STDOUT)
    p.communicate(input= bytes(r'uploader -i file.txt -d outputFolder\n','UTF-8'))[0]
    print (p.communicate()[0])
    p.stdin.close()

但没有运气。

【问题讨论】:

    标签: python windows subprocess stdin python-3.2


    【解决方案1】:
    1. 将命令参数作为参数传递,而不是作为标准输入
    2. 该命令可能直接从控制台读取用户名/密码,而不使用子进程的标准输入。在这种情况下,您可能需要 winpexpectSendKeys 模块。见my answer to a similar quesiton that has corresponding code examples

    这是一个示例,如何使用参数启动子进程、传递一些输入并将合并的子进程的 stdout/stderr 写入文件:

    #!/usr/bin/env python3
    import os
    from subprocess import Popen, PIPE, STDOUT
    
    command = r'fileLoc\uploader.exe -i file.txt -d outputFolder'# use str on Windows
    input_bytes = os.linesep.join(["username@email.com", "password"]).encode("ascii")
    with open('command_output.txt', 'wb') as outfile:
        with Popen(command, stdin=PIPE, stdout=outfile, stderr=STDOUT) as p:
            p.communicate(input_bytes)
    

    【讨论】:

    • Sebastian,我试图运行的程序,似乎冻结了。
    • @Rohit:它可能正在等待输入。要对其进行测试,请不要重定向标准输出并查看它是否在提示符下(输入用户名、密码等)停止(冻结)。
    • 是的,我尝试不使用 stdout = outfile,但它似乎仍然被冻结。我认为启动程序本身存在错误
    • 我的意思是,如果没有重定向,您应该能够看到子进程的输出——找出它阻塞的位置
    • 不幸的是,即使没有重定向,我也无法看到输出。我会拿出一些东西,看看它们是否有效,然后告诉你
    【解决方案2】:
    • 在将参数作为列表传递时不要使用shell=True
    • stdin.write 需要一个 bytes 对象作为参数。您尝试连接str
    • communicate() 将输入写入stdin 并返回一个输出为stdoutsterr 的元组,它一直等到该过程完成。只能使用一次,再次调用会报错。
    • 你确定你写的那行应该被传递给你的标准输入进程吗?不应该是您尝试运行的命令吗?

    【讨论】:

    • 1. Shell = True Solved 2. stdin.write:我之前解决了这个问题,但我忘了在这里写,所以现在我有 bytes(r'command','UTF-8')
    • 3.通信()是给我最大的问题,我不断收到 IOError: [Errno 22] Invalid argument Error。我只调用一次,我使用的格式如下: output = p.communicate(input = 'whatever the input is')[0] 即使我写: print (p.communicate()[0] ) 它仍然给我 IOError: [Errno 22] Invalid argument Error
    • 4.这是我要运行的命令,所以我尝试了 p = Popen([r'fileLoc/uploader.exe', 'command'],stdout=PIPE, stdin=PIPE, stderr=STDOUT) 和 p = Popen([ r'fileLoc/uploader.exe'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) 当我执行 p.stdout.readlines() 时,我得到相同的登录信息
    • 你试过Popen([r'fileLoc/uploader.exe', '-i', 'file.txt', '-o', 'outputFolder'], ...)吗?对我来说似乎更合理。
    • write 返回写入流的字节数,这就是您在交互式 interperter 会话中看到的内容。读取用户名/密码的程序通常设计为从终端读取,因此当您在标准输入上向它们发送数据时,它们通常无法正常工作
    猜你喜欢
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 2018-08-19
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    相关资源
    最近更新 更多