I have a python script which uses subprocess.check_call
to launch Wine (Windows Emulator on Linux), then the wine launches Z:\\Program Files (x86)\\PeaZip\\peazip.exe
.
Firstly, when I tested this python script in debugging mode python3 -u -m ipdb unpack_archive.py
, and set breakpoint around wine launch and run statements step by step, the Wine runs peazip.exe
successfully. That is, peazip successfully extract the PEA archive on Linux.
However, when I tested this python script not in debugging mode python3 unpack_archive.py
, then I find peazip.exe doesn't extract PEA archive successfully. So I suspect there is a synchronization problem in wine or python subprocess.check_call().
Now my workaround is, inserting time.sleep(1.0)
after launching wine :
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)
I checked the wine manual, it doesn't mention anything about synchronization. I also checked subprocess.check_call(). The document explicitly says the check_call() will wait for the command completed.
I don't want this workaround, because if the PEA archive file is very large, then the timeout value for sleep() must be larger, and we can't predict the sufficient timeout value before running it.
I referred to @jasonharper's suggestion. Use subprocess.check_output() instead of 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)
I tested it with python3 unpack_archive.py Kevin.pea
, which is a 2.0GB PEA archive. The extraction process costs 4 minutes 16 seconds. Three subfiles are unpacked successfully.
My understanding is that the wine
executable is not the actual emulator - it just launches a background process called wineserver
if it's not already running, tells it to run the Windows program, and then immediately exits itself - quite possibly before the Windows program has even started running.
One of the answers to this question suggests that piping the output of wine
to another program will delay things until the Windows program actually exits. In Python terms, this would be equivalent to using check_output()
instead of check_call()
, although I haven't tried this myself.