Python subprocess.check_call( ["wine"]..) 存在同步问题

标签 python python-3.x subprocess race-condition wine

我有一个 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/

相关文章:

python - Python中的类工厂

python - 如何测试是否存在具有特定名称的 Enum 成员?

python - 理解@property 装饰器和继承

python - 如何在单独的文件中组织所有不同的参数

python - 为什么子进程默认使用列表而不是带空格的字符串?

python - 在 Windows 中关闭 Python 中的主程序时,通过子进程传递参数并终止子进程

python - 转换列表中项目的更有效方法

python - EAGAIN 在 zeromq REQ/REP 上收到,没有阻塞套接字

python - os.fork() 之后的共享对象

python - 在 subprocess.call 中使用大于运算符