Home > Article > Backend Development > Detailed explanation of Python3's use of subprocess to implement pipeline pipe interactive operation read/write communication methods
Here we use the shell under Windows as an example:
subprocess *
To facilitate your understanding, we use a very simple piece of code to illustrate:
You can see that we used Popen to instantiate a p, created the subroutine cmd.exe, and then we gave him Stdin (standard input stream) and Stdout (standard output stream);
Also used subprocess. PIPE as a parameter, this is a special value used to indicate that these channels are to be opened. (In Python3.5, the run() method was added for better operations)
Then we continue
This information Does it look familiar? This is all the standard output of cmd!
Then these will be output:
The information "echo Hellwworlds\r\n" we just wrote has been written, it seems It did work!
Note that we use p.stdin.flush() to refresh the input buffer, and the output information also needs a "\r\n", at least under Windows systems This must be done, otherwise just refreshing (p.stdin.flush) will be invalid;
We successfully created the subroutine cmd.exe and wrote "echo Hellwworlds\r\n". Then cmd obtained and executed it, then returned to Hellwworlds. This is a very simple read Write interactions!
Now that we can simply read and write, let’s add some for and threading, the taste may be better~
#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()
Very good very good , guess what the output is?
The reason why there are many line breaks is that the results returned by cmd have line breaks, and then the print output will add a line break, so two lines are changed. You can consider using sys.stdout .write to output, so that there is no additional newline
In this case, you can make a basic read and write, then let's start encapsulation.
No more nonsense, just go to the code. If you really want to learn, please read it yourself carefully. Read the code.
Line 110
We have implemented all processes in one class, and can define three parameters, exit feedback function , ready feedback function and output feedback function.
# -*- 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()
Output:
You can see that our instructions are executed sequentially. Of course, the OS is also responsible for this.
So your extensible Pipe class should have been built, right?
A: The reason why I add the line number in front of this code is to prevent you from copying; because you may never understand what is going on here, but only know how to use it.
By the way:
It is best to refer to the official documents, which are already explained in great detail. subprocess.Popen.communicate may be more suitable for you, depending on what you want to do.
The above is the detailed content of Detailed explanation of Python3's use of subprocess to implement pipeline pipe interactive operation read/write communication methods. For more information, please follow other related articles on the PHP Chinese website!