Python子流程.check_调用([";wine";]..)存在同步问题

Python子流程.check_调用([";wine";]..)存在同步问题,python,python-3.x,subprocess,race-condition,wine,Python,Python 3.x,Subprocess,Race Condition,Wine,我有一个python脚本,它使用子进程。检查调用启动Wine(Linux上的Windows Emulator),然后Wine启动Z:\\Program Files(x86)\\PeaZip\\PeaZip.exe 首先,当我在调试模式下测试这个python脚本时,python3-u-mipdb unpack_archive.py,并在wine启动和运行语句周围逐步设置断点,wine成功运行了peazip.exe。也就是说,peazip在Linux上成功地提取了PEA归档文件 但是,当我在调试模式

我有一个python脚本,它使用
子进程。检查调用
启动Wine(Linux上的Windows Emulator),然后Wine启动
Z:\\Program Files(x86)\\PeaZip\\PeaZip.exe

首先,当我在调试模式下测试这个python脚本时,
python3-u-mipdb unpack_archive.py
,并在wine启动和运行语句周围逐步设置断点,wine成功运行了
peazip.exe
。也就是说,peazip在Linux上成功地提取了PEA归档文件

但是,当我在调试模式下测试这个python脚本时,发现peazip.exe没有成功地提取PEA归档文件。因此,我怀疑wine或python子流程中存在同步问题

现在我的解决方法是,在启动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)
我查过了,它没有提到任何关于同步的事情。我也查过了。文档明确表示check_call()将等待命令完成

我不想要这种解决方法,因为如果PEA归档文件非常大,那么sleep()的超时值必须更大,并且在运行它之前,我们无法预测足够的超时值


我提到了他的建议。使用subprocess.check_output()而不是check_call()


我用python3unpack_archive.py Kevin.pea
测试了它,它是一个2.0GB的pea存档。提取过程耗时4分16秒。三个子文件成功解包。

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


对的一个回答是,将
wine
的输出传输到另一个程序将延迟时间,直到Windows程序实际退出。在Python术语中,这相当于使用
check\u output()
而不是
check\u call()
,尽管我自己没有尝试过这一点。

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

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\u fn
(在
fork()
关闭子流程后运行,但在
wine
启动之前)获取一个锁,在
check\u call()
返回后,我们自己尝试获取该锁——如果它尚未释放,它将被阻止


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

好。我尝试使用
wineserver--front
。我发现在
peazip.exe
完成提取后,
wineserver
也将终止。在启动
wineserver
之前,我启动
wineserver--front
,并等待
wineserver
子进程终止。我尝试了您的示例代码,但遇到了以下异常:`Traceback(最近一次调用):文件“unpack\u archive.py”,第258行,在main()文件“unpack\u archive.py”中,第251行,在main中表示f,解包归档文件(arcname,outdir)中的sha1:解包归档文件关闭文件/usr/lib/python3.4/subprocess.py”中的第169行文件“解包归档文件.py”,第556行,检查调用retcode=call(*popenargs,**kwargs)子进程。子进程错误:preexec\fn中发生异常`这还不够详细--我需要实际的异常。您可以考虑用一个实际函数替换lambda,然后在提升之前打印一个堆栈跟踪。结果是第二个
fcntl.flock(lockfile,fcntl.LOCK_EX)
不会等到peazip执行完成。它仍然无法解决竞争条件。我不认为在测试期间已经有
wineserver
在运行?(否则,它将不得不关闭所有预先开放的FD以避免锁定……公平地说,这很可能发生)。
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)