Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erläuterung der Verwendung eines Unterprozesses durch Python3 zur Implementierung der Lese-/Schreibkommunikationsmethode für interaktive Pipeline-Pipe-Operationen

Detaillierte Erläuterung der Verwendung eines Unterprozesses durch Python3 zur Implementierung der Lese-/Schreibkommunikationsmethode für interaktive Pipeline-Pipe-Operationen

高洛峰
高洛峰Original
2017-03-20 10:28:124171Durchsuche

Hier verwenden wir die Shell unter Windows als Beispiel:

 subprocess  *

Um Ihr Verständnis zu erleichtern, verwenden wir zur Veranschaulichung einen sehr einfachen Code:

Detaillierte Erläuterung der Verwendung eines Unterprozesses durch Python3 zur Implementierung der Lese-/Schreibkommunikationsmethode für interaktive Pipeline-Pipe-Operationen

Sie können sehen, dass wir Popen verwendet haben, um ein p zu instanziieren, die Unterroutine cmd.exe erstellt und es dann Stdin (Standard-Eingabestream) und Stdout (Standard-Ausgabestream)

verwendet haben Geben Sie gleichzeitig subprocess.PIPE als Parameter an. Dies ist ein spezieller Wert, der angibt, dass diese Kanäle geöffnet werden sollen. (In Python3.5 wurde die run()-Methode für bessere Operationen hinzugefügt)

Dann fahren wir mit

Detaillierte Erläuterung der Verwendung eines Unterprozesses durch Python3 zur Implementierung der Lese-/Schreibkommunikationsmethode für interaktive Pipeline-Pipe-Operationen

diesen Informationen fort Kommt es dir bekannt vor? Dies ist die Standardausgabe von cmd!

Dann wird Folgendes ausgegeben:

Detaillierte Erläuterung der Verwendung eines Unterprozesses durch Python3 zur Implementierung der Lese-/Schreibkommunikationsmethode für interaktive Pipeline-Pipe-Operationen

Die Nachricht „echo Hellwworldsrn“, die wir gerade geschrieben haben, wurde geschrieben und scheint erfolgreich gewesen zu sein!

Beachten Sie, dass wir p.stdin.flush() verwenden, um den Eingabepuffer zu aktualisieren, und die Ausgabeinformationen benötigen zumindest in Windows-Systemen auch ein „rn“, ansonsten nur eine Aktualisierung (p.stdin.flush) wird ungültig sein;

Was genau haben wir getan?


Wir haben die Unterroutine cmd.exe erfolgreich erstellt und „echo Hellwworldsrn“ geschrieben. Dann hat cmd sie abgerufen und ausgeführt und ist dann zu Hellwworlds zurückgekehrt.

Fortgeschrittenere Verwendung

Jetzt, wo wir einfach lesen und schreiben können, fügen wir etwas für und Einfädeln hinzu, vielleicht schmeckt es besser~

#run.py  

from subprocess import * 
import threading 
import time

p =Popen('cmd.exe',shell=True,stdin=PIPE,stdout=PIPE)

def run():
    global p
    while True:
        line = p.stdout.readline() 
        if not line:  #空则跳出
            break
        print(">>>>>>",line.decode("GBK"))

    print("look up!!! EXIT ===")   #跳出


w =threading.Thread(target=run)

p.stdin.write("echo HELLW_WORLD!\r\n".encode("GBK"))
p.stdin.flush()
time.sleep(1) #延迟是因为等待一下线程就绪
p.stdin.write("exit\r\n".encode("GBK"))
p.stdin.flush()

w.start()

Sehr gut Großartig, rate mal Was ist die Ausgabe?

Detaillierte Erläuterung der Verwendung eines Unterprozesses durch Python3 zur Implementierung der Lese-/Schreibkommunikationsmethode für interaktive Pipeline-Pipe-Operationen

Der Grund für viele Zeilenumbrüche liegt darin, dass die von cmd zurückgegebenen Ergebnisse Zeilenumbrüche enthalten und die Druckausgabe dann einen Zeilenumbruch hinzufügt, sodass zwei Zeilen geändert werden . Sie können erwägen, sys.stdout .write für die Ausgabe zu verwenden, sodass kein zusätzlicher Zeilenumbruch erforderlich ist.

In diesem Fall können Sie einen einfachen Lese- und Schreibvorgang durchführen und dann mit der Kapselung beginnen.

Encapsulation Pipe


Kein Unsinn mehr, gehen Sie einfach zum Code. Wenn Sie es wirklich lernen möchten, lesen Sie ihn bitte selbst . Lesen Sie den Code.

Zeile 110

Wir haben alle Prozesse in einer Klasse implementiert und können drei Parameter definieren: Exit-Feedback--Funktion , Bereitschafts-Feedback-Funktion und Ausgabe-Feedback-Funktion.

# -*- coding:utf-8 -*-

import subprocess  
import sys
import threading

class LoopException(Exception):
    """循环异常自定义异常,此异常并不代表循环每一次都是非正常退出的"""
    def __init__(self,msg="LoopException"):
        self._msg=msg

    def __str__(self):
        return self._msg



class SwPipe():
    """
    与任意子进程通信管道类,可以进行管道交互通信
    """
    def __init__(self,commande,func,exitfunc,readyfunc=None,
        shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,code="GBK"):
        """
        commande 命令
        func 正确输出反馈函数
        exitfunc 异常反馈函数
        readyfunc 当管道创建完毕时调用
        """
        self._thread = threading.Thread(target=self.__run,args=(commande,shell,stdin,stdout,stderr,readyfunc))
        self._code = code
        self._func = func
        self._exitfunc = exitfunc
        self._flag = False
        self._CRFL = "\r\n"

    def __run(self,commande,shell,stdin,stdout,stderr,readyfunc):
        """ 私有函数 """
        try:
            self._process = subprocess.Popen(
                commande,
                shell=shell,
                stdin=stdin,
                stdout=stdout,
                stderr=stderr
                )  
        except OSError as e:
            self._exitfunc(e)
        fun = self._process.stdout.readline
        self._flag = True
        if readyfunc != None:
            threading.Thread(target=readyfunc).start() #准备就绪
        while True:
            line = fun()  
            if not line:  
                break
            try:
                tmp = line.decode(self._code)
            except UnicodeDecodeError:
                tmp =  \
                self._CRFL + "[PIPE_CODE_ERROR] <Code ERROR: UnicodeDecodeError>\n" 
                + "[PIPE_CODE_ERROR] Now code is: " + self._code + self._CRFL
            self._func(self,tmp)

        self._flag = False
        self._exitfunc(LoopException("While Loop break"))   #正常退出


    def write(self,msg):
        if self._flag:
            #请注意一下这里的换行
            self._process.stdin.write((msg + self._CRFL).encode(self._code)) 
            self._process.stdin.flush()
            #sys.stdin.write(msg)#怎么说呢,无法直接用代码发送指令,只能默认的stdin
        else:
            raise LoopException("Shell pipe error from &#39;_flag&#39; not True!")  #还未准备好就退出


    def start(self):
        """ 开始线程 """
        self._thread.start()

    def destroy(self):
        """ 停止并销毁自身 """
        process.stdout.close()
        self._thread.stop()
        del self
       





if __name__ == &#39;__main__&#39;:   #那么我们来开始使用它吧
    e = None

    #反馈函数
    def event(cls,line):#输出反馈函数
        sys.stdout.write(line)

    def exit(msg):#退出反馈函数
        print(msg)

    def ready():#线程就绪反馈函数
        e.write("dir")  #执行
        e.write("ping www.baidu.com")
        e.write("echo Hello!World 你好中国!你好世界!")
        e.write("exit")

    e = SwPipe("cmd.exe",event,exit,ready)
    e.start()

Ausgabe:

Detaillierte Erläuterung der Verwendung eines Unterprozesses durch Python3 zur Implementierung der Lese-/Schreibkommunikationsmethode für interaktive Pipeline-Pipe-Operationen

Sie können sehen, dass unsere Anweisungen nacheinander ausgeführt werden. Dafür ist natürlich auch das Betriebssystem verantwortlich.

Ihre erweiterbare Pipe-Klasse hätte also erstellt werden sollen, oder?

A: Der Grund, warum ich die Zeilennummer vor diesem Code hinzufüge, besteht darin, Sie am Kopieren zu hindern, da Sie möglicherweise nie verstehen, was hier passiert, sondern nur wissen, wie man es verwendet.

Übrigens:

Beziehen Sie sich am besten auf die offiziellen Dokumente, die bereits ausführlich erläutert werden. subprocess.Popen.communicate ist möglicherweise besser für Sie geeignet, je nachdem, was Sie tun möchten.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Verwendung eines Unterprozesses durch Python3 zur Implementierung der Lese-/Schreibkommunikationsmethode für interaktive Pipeline-Pipe-Operationen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn