我有一个 python 脚本,它使用 subprocess.check_call
启动 Wine(Linux 上的 Windows 模拟器),然后 wine 启动 Z:\\Program Files (x86)\\PeaZip\\peazip.exe
.
首先,当我在 Debug模式下测试这个Python脚本python3 -u -m ipdb unpack_archive.py
,并在wine启动和运行语句周围逐步设置断点时,Wine运行 pezip.exe
成功。即,peazip 在 Linux 上成功提取 PEA 存档。
但是,当我在 Debug模式下测试此 python 脚本时 python3 unpack_archive.py
时,我发现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 秒。三个子文件解压成功。
最佳答案
我的理解是,wine
可执行文件不是实际的模拟器 - 它只是启动一个名为 wineserver
的后台进程(如果它尚未运行),告诉它运行 Windows程序,然后立即自行退出 - 很可能在 Windows 程序开始运行之前。
this question 的答案之一建议将 wine
的输出通过管道传输到另一个程序会延迟执行,直到 Windows 程序实际退出。用 Python 术语来说,这相当于使用 check_output()
而不是 check_call()
,尽管我自己还没有尝试过。
关于Python subprocess.check_call( ["wine"]..) 存在同步问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45635565/