¿Cómo Python inicia un nuevo proceso y obtiene el resultado del programa?

¿Cómo Python inicia un nuevo proceso y obtiene el resultado del programa?

La primera forma, la más repugnante, bloqueará el proceso principal y, si no lo lee, a menudo congelará el registro.

import shlex
import subprocess
 
if __name__ == '__main__':
    shell_cmd = 'python3 subprogram.py'
    cmd = shlex.split(shell_cmd)
    p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while p.poll() is None:  # 这里死循环了.
        line = p.stdout.readline() # readlines(100)
        line = line.strip()
        if line:
            print('Subprogram output: [{}]'.format(line))
    if p.returncode == 0:
        print('Subprogram success')
    else:
        print('Subprogram failed')

Cuando use subprocess.PIPE en subprocess.Popen, use readlines () para leer el contenido del pipeline, y el programa se bloqueará. En este caso, solo necesita establecer el parámetro n en readlines (n).
Por ejemplo: p = subprocess.Popen (['nethogs', '- t', '- d'], stdout = subprocess.PIPE)
x = p.stdout.readlines (100)
Si quieres sacar todo el contenido en la tubería, solo necesita establecer el parámetro n muy grande, después de todo, la capacidad máxima del subproceso.PIPE es solo 64kb.

El segundo tipo: También es la forma más simple y elegante de escribir. Esta forma de escritura escribirá la salida en un archivo.
Esta forma es relativamente estable y no requiere un ciclo while para ejecutarse. No hay problema de bloquear el hilo principal La desventaja es que la salida no se puede obtener en tiempo real. Debe leer el archivo de registro usted mismo.

import subprocess

Logfilename = str(time.time())+"std.log"
with io.open(Logfilename, 'w',encoding='utf-8' ) as writer:
   self.proc = subprocess.Popen(
                [
                "python.exe", 
                "./UNet/pdseg/train.py",
                "--use_gpu",
                "--cfg=./static/dataset/optic_disc_seg/_UNetAIModels/M1/unet_optic.yaml",
                ],
               shell = True,
               stdout=writer
           )

El tercer método es intentar escribir una clase contenedora para ajustar la salida a la función de archivo. Interceptar la operación de escritura en el medio . Más tarde, resulta que esta idea es incorrecta. Porque no importa cómo la envuelvas, la salida en el subproceso no se enviará automáticamente al proceso principal. Dos objetos son completamente independientes en la memoria. La operación de salida del registro en el proceso hijo es operada directamente por el identificador de archivo pasado en el pasado. Se utiliza la operación básica del sistema operativo , que es básicamente el mismo que el del proceso padre. El código Python anterior es irrelevante, por lo que el paquete es inútil.

El cuarto es crear un nuevo hilo para leer la salida de la canalización del subproceso en un bucle . Sobre la base del primer método, establezca el parámetro stdout en subprocess.PIPE, de modo que el hilo principal no se atasque. La lectura es Más rápido Solo siente No es tan hermoso, necesita más recursos.

#读取日志的线程
class ReadLogThread(threading.Thread):
    def __init__(self, _pipe, onout):
        threading.Thread.__init__(self)
        self._pipe = _pipe
        self.logList = []
        self.onout = onout
    def run(self):
        while True:
            try:
                line = self._pipe.readline()
                if line == "":
                    break
                self.logList.append(line)
                if(self.onout!=None):
                    self.onout(line)
                # print("Thread=>",line)
            except Exception as eee:
                traceback.print_exc()
                # self.logList.append(str(eee))
                
 
    def get_log(self):
        return "".join(self.logList)
  

def main():
    writer = io.StringIO(initial_value='',NEWLINE='\n')
        self.proc = subprocess.Popen(
                arg,
                # [
                # "python.exe", 
                # "./UNet/pdseg/train.py",
                # "--use_gpu",
                # "--cfg=./static/dataset/optic_disc_seg/_UNetAIModels/M1/unet_optic.yaml",
                # ],
                shell = True,
                stdout=subprocess.PIPE
            )
 
        
         循环输出标准输出内容,避免阻塞
         self.stdoutThread = ReadLogThread(self.proc.stdout,onStdoutCallBack)
         self.stdoutThread.start()
        
         self.stderrThread = ReadLogThread(self.proc.stderr,onStderrCallBack)
         self.stderrThread.start()
         

El quinto método se basa en el segundo método de salida a un archivo. Lea la salida del archivo de registro del proceso secundario en un bucle. Luego, analice el contenido de salida usted mismo. La desventaja es que debe leerse desde el principio cada vez, que es lento. Lo
mejor también es Leer en subprocesos. Las operaciones del disco son relativamente grandes.

Resumen:
Personalmente, desde el punto de vista actual, es necesario ser estable y en tiempo real. La mejor manera es abrir un subproceso para leer la información de la canalización en un bucle. Y procesar el registro de salida en el subproceso. hilo.

Supongo que te gusta

Origin blog.csdn.net/phker/article/details/110386167
Recomendado
Clasificación