Maison >développement back-end >Tutoriel Python >Explication détaillée de l'utilisation du sous-processus par Python3 pour implémenter les méthodes de communication en lecture/écriture des opérations interactives des tuyaux de pipeline

Explication détaillée de l'utilisation du sous-processus par Python3 pour implémenter les méthodes de communication en lecture/écriture des opérations interactives des tuyaux de pipeline

高洛峰
高洛峰original
2017-03-20 10:28:124312parcourir

Nous utilisons ici le shell sous Windows comme exemple :

 subprocess  *

Pour faciliter votre compréhension, nous utilisons un bout de code très simple pour illustrer :

Explication détaillée de lutilisation du sous-processus par Python3 pour implémenter les méthodes de communication en lecture/écriture des opérations interactives des tuyaux de pipeline

Vous pouvez voir que nous avons utilisé Popen pour instancier un p, créé le sous-programme cmd.exe, puis nous lui avons donné Stdin (flux d'entrée standard) et Stdout (flux de sortie standard)

l'avons utilisé à ; en même temps subprocess.PIPE comme paramètre, il s'agit d'une valeur spéciale utilisée pour indiquer que ces canaux doivent être ouverts. (Dans Python3.5, la méthode run() a été ajoutée pour de meilleures opérations)

Ensuite, nous continuons avec

Explication détaillée de lutilisation du sous-processus par Python3 pour implémenter les méthodes de communication en lecture/écriture des opérations interactives des tuyaux de pipeline

ces informations ça vous semble familier ? C'est toute la sortie standard de cmd !

Ensuite, ceci sera affiché :

Explication détaillée de lutilisation du sous-processus par Python3 pour implémenter les méthodes de communication en lecture/écriture des opérations interactives des tuyaux de pipeline

Le message "echo Hellwworldsrn" que nous venons d'écrire a été écrit, et il semble avoir réussi !

Notez que nous utilisons p.stdin.flush() pour actualiser le tampon d'entrée, et les informations de sortie ont également besoin d'un "rn", au moins dans les systèmes Windows, sinon juste un rafraîchissement. (p.stdin.flush) sera invalide

Qu'avons-nous fait exactement ?


Nous avons créé avec succès le sous-programme cmd.exe et écrit "echo Hellwworldsrn". Ensuite, cmd l'a obtenu et exécuté, puis est retourné à Hellwworlds. Il s'agit d'une interaction de lecture-écriture très simple !

Utilisation plus avancée

Maintenant que nous pouvons simplement lire et écrire, ajoutons-en pour et le threading, cela aura peut-être meilleur goût ~

#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()

Très bien Super, devinez quel est le résultat ?

Explication détaillée de lutilisation du sous-processus par Python3 pour implémenter les méthodes de communication en lecture/écriture des opérations interactives des tuyaux de pipeline

La raison pour laquelle il y a de nombreux sauts de ligne est que les résultats renvoyés par cmd ont des sauts de ligne, puis la sortie d'impression ajoutera un saut de ligne, donc deux lignes sont modifiées . Vous pouvez envisager d'utiliser sys.stdout .write pour la sortie, afin qu'il n'y ait pas de nouvelle ligne supplémentaire

Dans ce cas, vous pouvez effectuer une lecture et une écriture de base, puis commençons l'encapsulation.

Tuyau d'encapsulation


Plus de bêtises, allez simplement au code Si vous voulez vraiment apprendre, lisez-le vous-même. Lisez attentivement le code.

Ligne 110

Nous avons implémenté tous les processus dans une seule classe et pouvons définir trois paramètres, un retour de sortie fonction , une fonction de retour prêt et une fonction de retour de sortie.

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

Sortie :

Explication détaillée de lutilisation du sous-processus par Python3 pour implémenter les méthodes de communication en lecture/écriture des opérations interactives des tuyaux de pipeline

Vous pouvez voir que nos instructions sont exécutées séquentiellement. Bien entendu, le système d’exploitation en est également responsable.

Donc, votre classe Pipe extensible aurait dû être construite, n'est-ce pas ?

A : La raison pour laquelle j'ajoute le numéro de ligne devant ce code est pour vous empêcher de le copier ; car vous ne comprendrez peut-être jamais ce qui se passe ici, mais vous saurez seulement comment l'utiliser.

D'ailleurs :

Il est préférable de se référer aux documents officiels, qui sont déjà expliqués de manière très détaillée. subprocess.Popen.communicate peut vous convenir mieux, selon ce que vous souhaitez faire.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn