Hier verwenden wir die Shell unter Windows als Beispiel:
subprocess *
Um Ihr Verständnis zu erleichtern, verwenden wir zur Veranschaulichung einen sehr einfachen Code:
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
diesen Informationen fort Kommt es dir bekannt vor? Dies ist die Standardausgabe von cmd!
Dann wird Folgendes ausgegeben:
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;
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.
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?
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.
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 '_flag' not True!") #还未准备好就退出 def start(self): """ 开始线程 """ self._thread.start() def destroy(self): """ 停止并销毁自身 """ process.stdout.close() self._thread.stop() del self if __name__ == '__main__': #那么我们来开始使用它吧 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:
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!