跟踪 Windows 10 上的 7zip 进度 Python
Tracking 7zip progress on Windows 10 with Python
我知道 7zip
有一些问题,它掩盖了试图调用它的代码的进度(不确定为什么)。
我看到 here -bsp1
标志应该显示隐藏的进度,但在 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)
运行 命令行中的 7z 命令在解包完成之前给了我一个很好的百分比。
在 Python 中,我得到 7z 的前奏打印输出(路径、类型等),之后只是 b''
,直到我按 Ctrl-c
7z 怎么知道我不是从“真实”终端调用它的?我能以某种方式让它看起来像我吗,也许使用 ctypes
和一些 windows 内核调用/API?
我看到了与此相关的术语“伪终端”,但我不确定它是否相关,如果相关,Windows' ConPTY API is hidden
不需要使用pseudo-terminal
。
我正在研究 windows 10.
直接使用stdout.readline()
获取输出可能很容易,但很难立即获取进度。(因为它包含\r
,它会将光标放在
行的开头,然后 7zip
使用 space 来填充它们。)。但 readline()
使用 \r\n
作为分隔符。
在我的示例中,我使用stdout.read(1)
直接获取输出。
由于进度条是12.So我用一个数字来查看。
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
这给我:
您可以改进它:
end
的条件。在我的代码中,我使用了if char == b"E"
。如果你把每个打印中的.decode("gbk")
去掉,我认为它不是good.Also行,你会看到文件名和编号,如:
虽然char split和cmd不同(一般应该是x% xx - filename
)所以有一行延迟:
我问这个问题有点晚了,但在过去 3 天里我一直在搜索类似 jizhihaoSAMA 的答案。这是一个很好的答案,我只是想分享一个我设法制作的更简单的答案。
所以打印 7zip
产生的所有行这个简单的脚本就足够了:
from subprocess import Popen, PIPE
cmd = [r'C:\Program Files-Zipz.exe', 'a', r'C:\ola\cenas.exe', "-sfx", r'C:\ola' + "\*", '-mmt', '-mx5', "-bsp1"]
final_str = ["Files read from disk:", "Archive size", "Everything is Ok"]
i = 0
with Popen(cmd, stdout=PIPE, bufsize=1,
universal_newlines=True) as p:
for line in p.stdout:
line = line.replace("\n", "")
print(line)
但是您可能不想看到 7zip
输出产生的空行。在这种情况下,您有以下可能的代码(前三行始终相同):
i = 0
with Popen(cmd, stdout=PIPE, bufsize=1, universal_newlines=True) as p:
for line in p.stdout:
i = i + 1
if "+" in line or i < 15 or any(s in line for s in final_str):
if "Files read from disk:" in line:
print("\n", line)
else:
print(line, end="")
现在因为您喜欢 7zip 输出在 cmd 中的原始方式,它在同一行中打印,您可以使用此代码:
i = 0
with Popen(cmd, stdout=PIPE, bufsize=1,
universal_newlines=True) as p:
for line in p.stdout:
i = i + 1
if "+" in line or i < 14 or any(s in line for s in final_str):
if "+" in line:
line = line.replace("\n", "")
print("\r", line, end="")
elif final_str[0] in line:
print("\n\n", line, end="")
else:
print(line, end="")
代码可能可以改进,但我也不是 python 方面的专家。这是我的第一个回答,所以如果有任何问题请告诉我:)
我知道 7zip
有一些问题,它掩盖了试图调用它的代码的进度(不确定为什么)。
我看到 here -bsp1
标志应该显示隐藏的进度,但在 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)
运行 命令行中的 7z 命令在解包完成之前给了我一个很好的百分比。
在 Python 中,我得到 7z 的前奏打印输出(路径、类型等),之后只是 b''
,直到我按 Ctrl-c
7z 怎么知道我不是从“真实”终端调用它的?我能以某种方式让它看起来像我吗,也许使用 ctypes
和一些 windows 内核调用/API?
我看到了与此相关的术语“伪终端”,但我不确定它是否相关,如果相关,Windows' ConPTY API is hidden
不需要使用pseudo-terminal
。
我正在研究 windows 10.
直接使用stdout.readline()
获取输出可能很容易,但很难立即获取进度。(因为它包含\r
,它会将光标放在
行的开头,然后 7zip
使用 space 来填充它们。)。但 readline()
使用 \r\n
作为分隔符。
在我的示例中,我使用stdout.read(1)
直接获取输出。
由于进度条是12.So我用一个数字来查看。
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
这给我:
您可以改进它:
end
的条件。在我的代码中,我使用了if char == b"E"
。如果你把每个打印中的.decode("gbk")
去掉,我认为它不是good.Also行,你会看到文件名和编号,如:
虽然char split和cmd不同(一般应该是x% xx - filename
)所以有一行延迟:
我问这个问题有点晚了,但在过去 3 天里我一直在搜索类似 jizhihaoSAMA 的答案。这是一个很好的答案,我只是想分享一个我设法制作的更简单的答案。
所以打印 7zip
产生的所有行这个简单的脚本就足够了:
from subprocess import Popen, PIPE
cmd = [r'C:\Program Files-Zipz.exe', 'a', r'C:\ola\cenas.exe', "-sfx", r'C:\ola' + "\*", '-mmt', '-mx5', "-bsp1"]
final_str = ["Files read from disk:", "Archive size", "Everything is Ok"]
i = 0
with Popen(cmd, stdout=PIPE, bufsize=1,
universal_newlines=True) as p:
for line in p.stdout:
line = line.replace("\n", "")
print(line)
但是您可能不想看到 7zip
输出产生的空行。在这种情况下,您有以下可能的代码(前三行始终相同):
i = 0
with Popen(cmd, stdout=PIPE, bufsize=1, universal_newlines=True) as p:
for line in p.stdout:
i = i + 1
if "+" in line or i < 15 or any(s in line for s in final_str):
if "Files read from disk:" in line:
print("\n", line)
else:
print(line, end="")
现在因为您喜欢 7zip 输出在 cmd 中的原始方式,它在同一行中打印,您可以使用此代码:
i = 0
with Popen(cmd, stdout=PIPE, bufsize=1,
universal_newlines=True) as p:
for line in p.stdout:
i = i + 1
if "+" in line or i < 14 or any(s in line for s in final_str):
if "+" in line:
line = line.replace("\n", "")
print("\r", line, end="")
elif final_str[0] in line:
print("\n\n", line, end="")
else:
print(line, end="")
代码可能可以改进,但我也不是 python 方面的专家。这是我的第一个回答,所以如果有任何问题请告诉我:)