Python通过Popen调用可执行文件后无法读取其写入的文件
问题描述
我有如下C++文件:
#include <cstdio> int main(int iArgC, char *apArgV[]) { int iResult = -1; if (iArgC > 1) { FILE *fOut = fopen(apArgV[1], "wt"); if (fOut != NULL) { fprintf(fOut, "hello\n"); fprintf(fOut, "goodbye\n"); fclose(fOut); printf("Written `%s`\n", apArgV[1]); iResult = 0; } else { printf("Couldn't open %s\n", apArgV[1]); } } else { printf("I need an argument\n"); } return 0; }
通过以下命令编译:
g++ -g -o hello hello.cpp
直接运行./hello /home/jody/hihi.txt时,hihi.txt文件可正常写入。
之后编写了如下Python脚本:
#!/usr/bin/python import subprocess as sp import time def callHello(file_name) : command = ["/home/jody/progs/polyhedronLED/version_c/hello", file_name] proc = sp.Popen(command, stdout=sp.PIPE, stderr=sp.PIPE) sOut, sError = proc.communicate() iResult = proc.returncode print("return code: %d"%iResult) print("Output: %s"%sOut) # -- end def if __name__ == '__main__': file_name0 = "/home/jody/hihi.txt" callHello(file_name0) ff = open(file_name0, "wt") lines = ff.readlines() ff.close() print("output\n%s"%lines) # -- end if
运行该脚本时得到如下输出:
return code: 0 Output: b'Written `/home/jody/hihi.txt`\n' Traceback (most recent call last): File "/home/jody/progs/polyhedronLED/version_c/./hellocall.py", line 22, in <module> lines = ff.readlines() ^^^^^^^^^^^^^^ io.UnsupportedOperation: not readable
事后检查输出目录时,hihi.txt文件已被成功写入。尝试在调用callHello()后添加time.sleep(5)延迟,结果依旧。编写bash脚本调用该可执行程序并读取文件却可正常运行。请问如何在Python中正确访问由子进程写入的文件?
解决方案
你的错误和子进程无关,核心问题是Python打开文件的模式用错了:
- 你用
"wt"模式打开文件,这是只写文本模式,无法执行读取操作,所以调用readlines()会抛出io.UnsupportedOperation: not readable错误。 - 要读取文件,需要改用
"rt"(只读文本)模式;如果需要同时支持读写,可使用"r+"模式;若要先清空文件再读写,用"w+",但这里你不需要清空,直接读即可。
修正后的Python代码片段:
if __name__ == '__main__': file_name0 = "/home/jody/hihi.txt" callHello(file_name0) # 改用只读模式打开文件 ff = open(file_name0, "rt") lines = ff.readlines() ff.close() print("output\n%s"%lines) # -- end if
更推荐使用Python的上下文管理器(with语句),它会自动帮你关闭文件,避免资源泄漏:
if __name__ == '__main__': file_name0 = "/home/jody/hihi.txt" callHello(file_name0) with open(file_name0, "rt") as ff: lines = ff.readlines() print("output\n%s"%lines) # -- end if
你之前加time.sleep(5)没用,因为proc.communicate()已经等待子进程执行完毕才返回,C++程序早就把文件写入磁盘并关闭了,问题根本不是子进程未完成写入。
内容的提问来源于stack exchange,提问作者user1479670
相关产品推荐
相关产品推荐

