>  기사  >  백엔드 개발  >  파이프라인 파이프 대화형 작업 읽기/쓰기 통신 방법을 구현하기 위해 Python3의 하위 프로세스 사용에 대한 자세한 설명

파이프라인 파이프 대화형 작업 읽기/쓰기 통신 방법을 구현하기 위해 Python3의 하위 프로세스 사용에 대한 자세한 설명

高洛峰
高洛峰원래의
2017-03-20 10:28:124252검색

여기에서는 Windows의 셸을 예로 사용합니다.

 subprocess  *

이해를 돕기 위해 매우 간단한 코드를 사용하여 설명합니다.

파이프라인 파이프 대화형 작업 읽기/쓰기 통신 방법을 구현하기 위해 Python3의 하위 프로세스 사용에 대한 자세한 설명

Popen을 사용하여 p를 인스턴스화하고 cmd.exe 서브루틴을 만든 다음 Stdin(표준 입력 스트림) 및 Stdout(표준 출력 스트림)을 제공하고

에서 하위 프로세스를 사용하는 것을 볼 수 있습니다. 동시에 PIPE를 매개변수로 사용하여 해당 채널이 열려 있음을 나타내는 데 사용되는 특수 값입니다. (Python3.5에서는 더 나은 작업을 위해 run() 메서드가 추가되었습니다.)

그런 다음

파이프라인 파이프 대화형 작업 읽기/쓰기 통신 방법을 구현하기 위해 Python3의 하위 프로세스 사용에 대한 자세한 설명

이 정보를 계속 진행합니다. 낯익은 것 같은데? 이것은 cmd의 표준 출력입니다!

그러면 다음과 같이 출력됩니다:

파이프라인 파이프 대화형 작업 읽기/쓰기 통신 방법을 구현하기 위해 Python3의 하위 프로세스 사용에 대한 자세한 설명

방금 작성한 "echo Hellwworldsrn" 메시지가 작성되었으며 성공한 것 같습니다!

입력 버퍼를 새로 고치려면 p.stdin.flush()를 사용하고, 적어도 Windows 시스템에서는 출력 정보에도 "rn"이 필요합니다. 그렇지 않으면 그냥 새로 고치기만 하면 됩니다. (p.stdin.flush)는 유효하지 않습니다.

우리가 정확히 무엇을 했나요?
고급 활용

이제 간단하게 읽고 쓸 수 있으니 for와 threading을 추가하면 더 맛있을 것 같아요~

#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를 사용하여 추가 줄 바꿈이 없도록 고려할 수 있습니다 파이프라인 파이프 대화형 작업 읽기/쓰기 통신 방법을 구현하기 위해 Python3의 하위 프로세스 사용에 대한 자세한 설명

이 경우 기본 읽기 및 쓰기를 수행한 다음 캡슐화를 시작하겠습니다.

Encapsulation Pipe

더 이상 말도 안되는 소리는 그만하고, 정말 배우고 싶다면 코드로 가보세요. 코드를 주의 깊게 읽어보세요.


110행

모든 프로세스를 하나의 클래스로 구현했으며 세 가지 매개변수, 종료 피드백

기능

, 준비 피드백 기능 및 출력 피드백 기능을 정의할 수 있습니다.

# -*- 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()
출력:

명령이 순차적으로 실행되는 것을 볼 수 있습니다. 물론 OS도 이에 대한 책임이 있습니다. 파이프라인 파이프 대화형 작업 읽기/쓰기 통신 방법을 구현하기 위해 Python3의 하위 프로세스 사용에 대한 자세한 설명

그럼 확장 가능한 Pipe 클래스가 만들어졌어야죠?

A: 이 코드 앞에 줄 번호를 추가하는 이유는 복사를 방지하기 위한 것입니다. 왜냐하면 여기서 무슨 일이 일어나고 있는지 전혀 이해하지 못할 수도 있지만 사용법만 알 수 있기 때문입니다.

그나저나:

이미 자세히 설명되어 있는 공식 문서를 참조하는 것이 가장 좋습니다. 원하는 작업에 따라 subprocess.Popen.communicate가 더 적합할 수 있습니다.

위 내용은 파이프라인 파이프 대화형 작업 읽기/쓰기 통신 방법을 구현하기 위해 Python3의 하위 프로세스 사용에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.