Pythonsubprocess.check_调用([“wine”]…)有一个同步问题

2024-09-26 22:09:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个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_调用(). 在

现在我的解决方法是,在启动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_输出()而不是check\u call()

^{pr2}$

我用python3 unpack_archive.py Kevin.pea测试了它,这是一个2.0GB的PEA存档。提取过程需要4分16秒。三个子文件解包成功。在


Tags: py脚本checksleepcallexepython3pea
2条回答

考虑使用咨询锁定来阻止,直到进程退出:

lockfile=open(tmpfile, 'a')
subprocess.check_call([
         "wine", "/home/acteam/.wine/drive_c/Program Files (x86)/PeaZip/peazip.exe",
        "-ext2here", to_wine_path(tmpfile)],
    preexec_fn=lambda: fcntl.flock(lockfile, fcntl.LOCK_EX),
    close_fds=False)
fcntl.flock(lockfile, fcntl.LOCK_EX)

在这里,我们的preexec_fn(在fork()关闭子进程之后,但在wine启动之前运行)获取一个锁,check_call()返回后,我们尝试自己获取该锁,如果它尚未释放,它将被阻塞。在

(请注意,您需要确保wine不会在程序退出之前关闭该文件描述符;如果确实关闭了,一种避免这种情况的方法是在作为stdin、stdout或stderr传递的描述符上创建锁)。在

我的理解是,wine可执行文件并不是真正的仿真器——它只是启动一个名为wineserver的后台进程,如果它还没有运行,告诉它运行Windows程序,然后立即退出它自己——很可能是在Windows程序开始运行之前。在

this question的一个答案表明,将wine的输出通过管道传输到另一个程序将延迟时间,直到Windows程序实际退出。在Python术语中,这相当于使用check_output()而不是{},尽管我自己没有尝试过。在

相关问题 更多 >

    热门问题