여기에서는 Windows의 셸을 예로 사용합니다.
subprocess *
이해를 돕기 위해 매우 간단한 코드를 사용하여 설명합니다.
Popen을 사용하여 p를 인스턴스화하고 cmd.exe 서브루틴을 만든 다음 Stdin(표준 입력 스트림) 및 Stdout(표준 출력 스트림)을 제공하고
에서 하위 프로세스를 사용하는 것을 볼 수 있습니다. 동시에 PIPE를 매개변수로 사용하여 해당 채널이 열려 있음을 나타내는 데 사용되는 특수 값입니다. (Python3.5에서는 더 나은 작업을 위해 run() 메서드가 추가되었습니다.)
그런 다음
이 정보를 계속 진행합니다. 낯익은 것 같은데? 이것은 cmd의 표준 출력입니다!
그러면 다음과 같이 출력됩니다:
방금 작성한 "echo Hellwworldsrn" 메시지가 작성되었으며 성공한 것 같습니다!
입력 버퍼를 새로 고치려면 p.stdin.flush()를 사용하고, 적어도 Windows 시스템에서는 출력 정보에도 "rn"이 필요합니다. 그렇지 않으면 그냥 새로 고치기만 하면 됩니다. (p.stdin.flush)는 유효하지 않습니다.
#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()
줄 바꿈이 많은 이유는 cmd에서 반환된 결과에 줄 바꿈이 있고, 그러면 인쇄 출력에 줄 바꿈이 추가되므로 두 줄이 변경되기 때문입니다. . 출력에 sys.stdout .write를 사용하여 추가 줄 바꿈이 없도록 고려할 수 있습니다
이 경우 기본 읽기 및 쓰기를 수행한 다음 캡슐화를 시작하겠습니다. Encapsulation Pipe기능
, 준비 피드백 기능 및 출력 피드백 기능을 정의할 수 있습니다.# -*- 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()출력:
명령이 순차적으로 실행되는 것을 볼 수 있습니다. 물론 OS도 이에 대한 책임이 있습니다.
그럼 확장 가능한 Pipe 클래스가 만들어졌어야죠? A: 이 코드 앞에 줄 번호를 추가하는 이유는 복사를 방지하기 위한 것입니다. 왜냐하면 여기서 무슨 일이 일어나고 있는지 전혀 이해하지 못할 수도 있지만 사용법만 알 수 있기 때문입니다. 그나저나: 이미 자세히 설명되어 있는 공식 문서를 참조하는 것이 가장 좋습니다. 원하는 작업에 따라 subprocess.Popen.communicate가 더 적합할 수 있습니다.위 내용은 파이프라인 파이프 대화형 작업 읽기/쓰기 통신 방법을 구현하기 위해 Python3의 하위 프로세스 사용에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!