如何在python中捕获命令的输出?

时间:2019-05-29 14:50:06

标签: python list subprocess

我有一个连接数据库并获取结果的文件。现在必须使用python 3运行文件,而我的项目使用python 2.7。因此,我使用subprocess模块将文件作为命令行运行。这是我叫文件的方式。

import subprocess
import ast

def execute_python3(param):
    param = param.replace("\\", "")
    param = "\"" + param + "\""

    cmd = "python3 " + "get_db_result.py" + " " + param

    result = subprocess.check_output(cmd, shell=True)
    return ast.literal_eval(result)

execute_python3(sql_query)

在此命令中,我正在将sql查询传递给get_db_result文件。

get_db_result.py文件看起来像这样

import sys
def get_result():
    param = sys.argv[1]
    '''
    Logic to get result from db
    '''
    result = db_output
    print(result)

if __name__ == "__main__":
    get_result()

现在的问题是,当我从db获取输出时,我必须对print模块捕获的输出执行subprocess。这使得很难解析程序要用于进一步工作的输出。例如,当我收到这样的输出

"[(u'Delhi', 20199330), (u'Mumbai', 134869470), (u'Kolkata', 6678446)]"

这是一个元组的字符串列表,可以通过执行类似ast.literal_eval(result)

的操作将其转换为元组列表。

但是有时候我会得到这样的输出

"[(datetime.date(2019, 5, 27), 228.168093587), (datetime.date(2019, 5, 28), 228.834493641)]"

这里ast不理解datetime。甚至json.loads()对此都不起作用。

如何在不使用print的情况下从文件捕获输出并将其直接返回到subprocess。甚至有可能吗?

1 个答案:

答案 0 :(得分:0)

您需要在两端对数据进行序列化和反序列化。最简单的解决方案是使用Python的pickle模块,并希望在Python 3端序列化的类型与在反序列化Python 2端的类型足够相似。您需要在发送端将使用的协议指定为接收端可以理解的版本:

具有安全调用子进程的接收器(中间没有shell进程)

#!/usr/bin/env python
import pickle
import subprocess


def execute_python3(param):
    result = subprocess.check_output(['python3', 'get_db_result.py', param])
    return pickle.loads(result)


def main():
    execute_python3(sql_query)


if __name__ == '__main__':
    main()

发件人,明确选择一个Python 2仍然可以理解的pickle协议。

#!/usr/bin/env python3
import sys
import pickle


def get_result():
    param = sys.argv[1]
    '''
    Logic to get result from db
    '''
    result = db_output
    pickle.dump(result, sys.stdout.buffer, protocol=2)


if __name__ == '__main__':
    get_result()

如果由于Python 2和3之间的(反)序列化对象的差异而导致此方法不起作用,则必须回退以显式(反)序列化数据,例如JSON,如来自杰伊。