I understand 7zip
has some issue, where it masks its progress from code that tries to call it (not sure why).
I saw here that -bsp1
flag should show the hidden progress, but still nothing in Python:
from subprocess import Popen, PIPE
from time import sleep
cmd = Popen('7z.exe e D:\stuff.rar -od:\stuff -aoa -bsp1'.split(), stdout=PIPE, stderr=PIPE)
while cmd.poll() !=0: # Not sure this helps anything
out = cmd.stdout.read()
print(out)
sleep(1)
Running the 7z command in the command line gives me a nice percentage until unpacking is done.
In Python, I get 7z's prelude printout (Path, Type etc.) and after that just b''
until I press Ctrl-c
How does 7z know I'm calling it not from the "real" terminal? Can I somehow make it look like I am, maybe using ctypes
and some windows kernel call / API?
I saw the term "pseudo terminal" mentioned in regards to this, but I'm not sure it's relevant, and if it is, Windows' ConPTY API is hidden
There is no need to use pseudo-terminal
.
I am working on windows 10.
Get the output could be easy but it is hard to get the progress immediately if you use stdout.readline()
directly.(Because it contains \r
and it will put the cursor in
start of the line, then 7zip
use space to fill them.).But readline()
use \r\n
as the seperator.
In my example, I use stdout.read(1)
to get the output directly.
Due to the progress line is 12.So I use a number to check it.
import subprocess
s = "D:/7-Zip/7z.exe e E:/work/Compile/python/python_project/temp/test.zip -oE:/work/Compile/python/python_project/temp/test -aoa -bsp1"
p = subprocess.Popen(s.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
i = 0
while True:
line = p.stdout.readline()
if line:
if i == 11:
s = b""
while True:
char = p.stdout.read(1)
if char == b"E": # "Everything is ok" means end
break
s += char
if char == b"%":
print(s.decode("gbk"))
s = b""
print(line.decode("gbk"))
i += 1
You could improve it:
The condition of end
.In my code, I used if char == b"E"
.I don't think it is good.Also if you remove the .decode("gbk")
in each print line, you will see the file name and the number,like:
Though the char split is different from the cmd(Normally it should be x% xx - filename
)So there is one line delay: