Отслеживание прогресса 7zip на Windows 10 с Python - PullRequest
1 голос
/ 04 августа 2020

Я понимаю, что 7zip имеет некоторую проблему, когда он маскирует свой прогресс из кода, который пытается вызвать его (не знаю почему).

Я видел здесь этот -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 в командной строке дает мне хороший процент до тех пор, пока распаковка не будет завершена.

In Python, Я получаю распечатку прелюдии 7z (Путь, Тип и т.д. c.), А после этого просто b'', пока я не нажму Ctrl-c

Как 7z узнает, что я звоню ему не из «настоящего " Терминал? Могу ли я как-то сделать так, чтобы это выглядело так, как будто я использую ctypes и некоторые windows вызовы ядра / API?

Я видел термин «псевдотерминал», упомянутый в связи с этим, но я не убедитесь, что это актуально, и если это так, Windows ' ConPTY API скрытый

1 Ответ

2 голосов
/ 06 августа 2020

Нет необходимости использовать pseudo-terminal. Я работаю над windows 10.

Получить результат может быть легко, но трудно сразу получить прогресс, если вы используете stdout.readline() напрямую (потому что он содержит \r, и он поместит курсор в начале строки, затем 7zip используйте пробел для их заполнения.). Но readline() использует \r\n в качестве разделителя.

В моем примере я использую stdout.read(1), чтобы получить результат прямо. Из-за того, что строка прогресса 12, поэтому я использую номер для проверки.

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

Это дает мне: enter image description here


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:

enter image description here

Though the char split is different from the cmd(Normally it should be x% xx - filename)So there is one line delay:

введите описание изображения здесь

...