我有一个连接数据库并获取结果的文件。现在必须使用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
。甚至有可能吗?
答案 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,如来自杰伊。