将Python脚本输出传递给另一个程序的stdin

2 投票
1 回答
2717 浏览
提问于 2025-04-16 18:21

我有一个应用程序,可以直接从终端输入数据,或者我可以用管道把另一个程序的输出传递给这个程序的标准输入(stdin)。我想用Python来生成输出,确保格式正确,然后把这个输出从同一个脚本传递给这个程序的标准输入。以下是代码:

#!/usr/bin/python
import os 
import subprocess
import plistlib
import sys

def appScan():
    os.system("system_profiler -xml SPApplicationsDataType > apps.xml")
    appList = plistlib.readPlist("apps.xml")
    sys.stdout.write( "Mac_App_List\n"
    "Delimiters=\"^\"\n"
    "string50 string50\n"
    "Name^Version\n")
    appDict = appList[0]['_items']
    for x in appDict:
        if 'version' in x:
           print x['_name'] + "^" + x['version'] + "^"
        else:
           print x['_name'] + "^" + "no version found" + "^"
proc = subprocess.Popen(["/opt/altiris/notification/inventory/lib/helpers/aex-     sendcustominv","-t","-"], shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
proc.communicate(input=appScan())

但是不知为什么,我调用的这个子进程对传入的标准输入不太满意。不过如果我去掉子进程的部分,只让脚本打印到标准输出(stdout),然后从终端调用这个脚本(python appScan.py | aex-sendcustominv),aex-sendcustominv就能正常接受输入。有没有办法把Python中一个函数的输出发送到子进程的标准输入呢?

1 个回答

3

问题在于 appScan() 只会输出到标准输出(也就是屏幕上),而 appScan() 返回的是 None,所以 proc.communicate(input=appScan()) 实际上等同于 proc.communicate(input=None)。你需要让 appScan 返回一个字符串。

试试这个(没有测试过):

def appScan():
    os.system("system_profiler -xml SPApplicationsDataType > apps.xml")
    appList = plistlib.readPlist("apps.xml")
    output_str = 'Delimiters="^"\nstring50 string50\nName^Version\n'
    appDict = appList[0]['_items']
    for x in appDict:
        if 'version' in x:
           output_str = output_str + x['_name'] + "^" + x['version'] + "^"
        else:
           output_str = output_str + x['_name'] + "^" + "no version found" + "^"
    return output_str

proc = subprocess.Popen(["/opt/altiris/notification/inventory/lib/helpers/aex-     sendcustominv","-t","-"], shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
proc.communicate(input=appScan())

撰写回答