【发布时间】:2017-08-13 23:05:57
【问题描述】:
我有一个 python 脚本,它使用 subprocess.check_call 启动 Wine(Linux 上的 Windows 模拟器),然后 wine 启动 Z:\\Program Files (x86)\\PeaZip\\peazip.exe。
首先,当我在调试模式python3 -u -m ipdb unpack_archive.py 下测试这个python 脚本,并逐步围绕wine 启动和运行语句设置断点时,Wine 成功运行peazip.exe。即 peazip 在 Linux 上成功解压 PEA 压缩包。
但是,当我在调试模式python3 unpack_archive.py 下测试这个 python 脚本时,我发现 peazip.exe 没有成功提取 PEA 存档。所以我怀疑wine或python subprocess.check_call()中存在同步问题。
现在我的解决方法是,在启动 wine 后插入 time.sleep(1.0):
elif 'PEA archive' in ftype:
if splitext(arcname)[1] != '.pea':
tmpfile = os.path.join(tmpdir, basename(arcname))+'.pea'
else:
tmpfile = os.path.join(tmpdir, basename(arcname))
shutil.copy(arcname, tmpfile)
subprocess.check_call(["wine", "/home/acteam/.wine/drive_c/Program Files (x86)/PeaZip/peazip.exe",
"-ext2here", to_wine_path(tmpfile)])
import time
time.sleep(1.0) # if we don't sleep, then peazip.exe won't extract file successfully
os.remove(tmpfile)
copy_without_symlink(tmpdir, outdir)
我检查了wine manual,它没有提到任何关于同步的内容。我还检查了subprocess.check_call()。该文档明确表示 check_call() 将等待命令完成。
我不想要这个变通方法,因为如果 PEA 存档文件非常大,那么 sleep() 的超时值必须更大,并且在运行它之前我们无法预测足够的超时值。
我参考了@jasonharper的建议。使用 subprocess.check_output() 而不是 check_call()
elif 'PEA archive' in ftype:
if splitext(arcname)[1] != '.pea':
tmpfile = os.path.join(tmpdir, basename(arcname))+'.pea'
else:
tmpfile = os.path.join(tmpdir, basename(arcname))
shutil.copy(arcname, tmpfile)
subprocess.check_output(["wine", "/home/acteam/.wine/drive_c/Program Files (x86)/PeaZip/peazip.exe",
"-ext2here", to_wine_path(tmpfile)])
os.remove(tmpfile)
copy_without_symlink(splitext(tmpfile)[0], outdir)
我使用 python3 unpack_archive.py Kevin.pea 对其进行了测试,这是一个 2.0GB 的 PEA 存档。提取过程耗时 4 分 16 秒。三个子文件解压成功。
【问题讨论】:
标签: python python-3.x subprocess race-condition wine