【问题标题】:Can you open stdin as a file on MS Windows in Python?您可以在 Python 中的 MS Windows 上将标准输入作为文件打开吗?
【发布时间】:2012-01-22 07:06:59
【问题描述】:

在 Linux 上,我使用 supbprocess.Popen 来运行应用程序。该应用程序的命令行需要输入文件的路径。我了解到我可以将路径 /dev/stdin 传递到命令行,然后使用 Python 的 subproc.stdin.write() 将输入发送到子进程。

import subprocess
kw['shell'] = False
kw['executable'] = '/path/to/myapp'
kw['stdin'] = subprocess.PIPE
kw['stdout'] = subprocess.PIPE
kw['stderr'] = subprocess.PIPE
subproc = subprocess.Popen(['','-i','/dev/stdin'],**kw)
inbuff = [u'my lines',u'of text',u'to process',u'go here']
outbuff = []
conditionbuff = []

def processdata(inbuff,outbuff,conditionbuff):
    for i,line in enumerate(inbuff):
        subproc.stdin.write('%s\n'%(line.encode('utf-8').strip()))
        line = subproc.stdout.readline().strip().decode('utf-8')
        if 'condition' in line:
            conditionbuff.append(line)
        else:
            outbuff.append(line)

processdata(inbuff,outbuff,conditionbuff)

此应用程序还有一个 MS Windows 版本。在 MS Windows 上是否有使用 /dev/stdin 的等效方案,或者是 Linux (Posix) 特定的解决方案?

【问题讨论】:

标签: python windows linux stdin


【解决方案1】:

如果myapp- 视为表示标准输入的特殊文件名,则:

from subprocess import PIPE, Popen

p = Popen(['/path/to/myapp', '-i', '-'], stdin=PIPE, stdout=PIPE)
stdout, _ = p.communicate('\n'.join(inbuff).encode('utf-8'))
outbuff = stdout.decode('utf-8').splitlines()

如果你不能通过-,那么你可以使用一个临时文件:

import os
import tempfile

with tempfile.NamedTemporaryFile(delete=False) as f:
     f.write('\n'.join(inbuff).encode('utf-8'))

p = Popen(['/path/to/myapp', '-i', f.name], stdout=PIPE)
outbuff, conditionbuff = [], []
for line in iter(p.stdout.readline, ''):
    line = line.strip().decode('utf-8')
    if 'condition' in line:
        conditionbuff.append(line)
    else:
        outbuff.append(line)
p.stdout.close()
p.wait()
os.remove(f.name) #XXX add try/finally for proper cleanup

要抑制stderr,您可以将open(os.devnull, 'wb') 作为stderr 传递给Popen

【讨论】:

  • 我试过'-',这个应用程序不支持它。此外,在这种情况下,communicate() 将不起作用,因为我需要此代码中未显示的逐行控制。
  • @tahoar:您能否更新您的问题并详细说明“逐行控制”在您的情况下的含义?
  • @sebastion:查看更新。 communicate() 的另一个问题是加载进程可能需要一些时间(10-15 分钟)。这种方法不仅让我可以逐行处理数据,而且我还可以多次调用循环而无需重新加载应用程序。我怀疑 STDIN 问题是特定于操作系统的,我仅限于 Posix 平台,而无需更改我正在调用的应用程序。
  • @tahoar:我已经更新了使用临时文件作为输入并逐行读取输出的答案。
  • 是的,当然是临时文件。我没有想清楚。我可以测试操作系统并在 Window 上使用临时文件。谢谢。
【解决方案2】:

总在黑暗中拍摄,但con: 是控制台设备的名称(你知道,很好,来自 DOS 的 copy con newfile.txt)。您也许可以将 con: 作为参数传递给不接受“-”的程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-12
    • 2014-07-10
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    • 2013-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多