代码之家  ›  专栏  ›  技术社区  ›  MikimotoH

Python子进程。check\u调用([“wine”]…)存在同步问题

  •  2
  • MikimotoH  · 技术社区  · 7 年前

    我有一个python脚本,它使用 subprocess.check_call Z:\\Program Files (x86)\\PeaZip\\peazip.exe .

    首先,当我在调试模式下测试这个python脚本时 python3 -u -m ipdb unpack_archive.py peazip.exe 成功地也就是说,peazip在Linux上成功地提取了PEA存档。

    然而,当我在调试模式下测试这个python脚本时 python3 unpack_archive.py ,然后我找到了peazip。exe无法成功提取PEA存档。所以我怀疑wine或python子进程中存在同步问题。check_call()。

    现在我的解决方法是插入 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\u call()将等待命令完成。

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


    我提到 @jasonharper 的建议。使用子流程。check\u output()而不是check\u 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秒。三个子文件成功解包。

    2 回复  |  直到 7 年前
        1
  •  1
  •   jasonharper    7 年前

    我的理解是 wine wineserver 如果它还没有运行,告诉它运行Windows程序,然后立即退出自己-很可能在Windows程序开始运行之前。

    this question 建议管道输出 葡萄酒 到另一个程序将延迟事情,直到Windows程序实际退出。在Python中,这相当于使用 check_output() 而不是 check_call() ,尽管我自己没有试过。

        2
  •  1
  •   Charles Duffy Tom    7 年前

    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传递的描述符上创建锁)。