搜索
首页后端开发Python教程详解Python3利subprocess实现管道pipe交互操作读/写通信方法

这里我们用Windows下的shell来举例:

 subprocess  *

为了方便你理解,我们用一个很简单的一段代码来说明:

详解Python3利subprocess实现管道pipe交互操作读/写通信方法

可以看见我们利用Popen实例化了一个p,创建了子程序cmd.exe,然后我们给他的的Stdin(标准输入流)Stdout(标准输出流);

同时使用了subprocess.PIPE 作为参数,这个是一个特殊值,用于表明这些通道要开放。(在Python3.5,加入了run()方法来进行更好的操作)

然后我们继续

详解Python3利subprocess实现管道pipe交互操作读/写通信方法

这些信息是不是很眼熟?这都是cmd的标准输出!

然后就会输出这些:

详解Python3利subprocess实现管道pipe交互操作读/写通信方法

我们刚刚所写入的信息"echo Hellwworlds\r\n"已经被写入了,看起来确实成功了!

注意一下我们使用了 p.stdin.flush() 来对输入缓存区进行刷新,输出的信息也需要一个 "\r\n",至少在 Windows 系统下必须这样做,否则只刷新(p.stdin.flush)的话是无效的;

我们到底做了什么?


我们成功的创建了子程序 cmd.exe,并且写入"echo Hellwworlds\r\n" ,然后cmd获取了并且执行,于是返回 Hellwworlds,这就是一次很简单的读写交互! 

更高级的使用

既然我们已经可以简单的读写了,那么加点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()

很好很好,猜猜输出什么?

详解Python3利subprocess实现管道pipe交互操作读/写通信方法

有很多换行的原因是cmd返回的结果有换行,然后print输出会加一个换行,所以就换了两行,你可以考虑使用 sys.stdout.write 来输出,这样就没有附加的换行了

这样的话,你可以制作一个基础的读写了,那么我们开始封装吧。

 

 

封装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()

输出:

 详解Python3利subprocess实现管道pipe交互操作读/写通信方法

 你可以看见,我们的指令都顺序的执行了。当然了这里面还有OS的功劳。

 

那么你的可扩展的Pipe类应该已经构建完毕了吧?

A: 我之所以要在这种代码前面加入行数的原因就是为了防止你复制;因为你可能永远不会明白这里究竟发生了什么,而是只懂得了使用。

顺便一提:

最好去参考一下官方的文档,已经讲得非常详细了。subprocess.Popen.communicate 或许更适合你,看你是要进行什么事情。

 

以上是详解Python3利subprocess实现管道pipe交互操作读/写通信方法的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Python脚本可能无法在UNIX上执行的一些常见原因是什么?Python脚本可能无法在UNIX上执行的一些常见原因是什么?Apr 28, 2025 am 12:18 AM

Python脚本在Unix系统上无法运行的原因包括:1)权限不足,使用chmod xyour_script.py赋予执行权限;2)Shebang行错误或缺失,应使用#!/usr/bin/envpython;3)环境变量设置不当,可打印os.environ调试;4)使用错误的Python版本,可在Shebang行或命令行指定版本;5)依赖问题,使用虚拟环境隔离依赖;6)语法错误,使用python-mpy_compileyour_script.py检测。

举一个场景的示例,其中使用Python数组比使用列表更合适。举一个场景的示例,其中使用Python数组比使用列表更合适。Apr 28, 2025 am 12:15 AM

使用Python数组比列表更适合处理大量数值数据。1)数组更节省内存,2)数组对数值运算更快,3)数组强制类型一致性,4)数组与C语言数组兼容,但在灵活性和便捷性上不如列表。

在Python中使用列表与数组的性能含义是什么?在Python中使用列表与数组的性能含义是什么?Apr 28, 2025 am 12:10 AM

列表列表更好的forflexibility andmixDatatatypes,何时出色的Sumerical Computitation sand larged数据集。1)不可使用的列表xbilese xibility xibility xibility xibility xibility xibility xibility xibility xibility xibility xibles and comply offrequent elementChanges.2)

Numpy如何处理大型数组的内存管理?Numpy如何处理大型数组的内存管理?Apr 28, 2025 am 12:07 AM

numpymanagesmemoryforlargearraysefefticefticefipedlyuseviews,副本和内存模拟文件.1)viewsAllowSinglicingWithOutCopying,直接modifytheoriginalArray.2)copiesCanbecopy canbecreatedwitheDedwithTheceDwithThecevithThece()methodervingdata.3)metservingdata.3)memore memore-mappingfileShessandAstaStaStstbassbassbassbassbassbassbassbassbassbassbb

哪个需要导入模块:列表或数组?哪个需要导入模块:列表或数组?Apr 28, 2025 am 12:06 AM

Listsinpythondonotrequireimportingamodule,helilearraysfomthearraymoduledoneedanimport.1)列表列表,列表,多功能和canholdMixedDatatatepes.2)arraysaremoremoremoremoremoremoremoremoremoremoremoremoremoremoremoremoremeremeremeremericdatabuteffeftlessdatabutlessdatabutlessfiblesible suriplyElsilesteletselementEltecteSemeTemeSemeSemeSemeTypysemeTypysemeTysemeTypysemeTypepe。

可以在Python数组中存储哪些数据类型?可以在Python数组中存储哪些数据类型?Apr 27, 2025 am 12:11 AM

pythonlistscanStoryDatatepe,ArrayModulearRaysStoreOneType,and numpyArraySareSareAraysareSareAraysareSareComputations.1)列出sareversArversAtileButlessMemory-Felide.2)arraymoduleareareMogeMogeNareSaremogeNormogeNoreSoustAta.3)

如果您尝试将错误的数据类型的值存储在Python数组中,该怎么办?如果您尝试将错误的数据类型的值存储在Python数组中,该怎么办?Apr 27, 2025 am 12:10 AM

WhenyouattempttostoreavalueofthewrongdatatypeinaPythonarray,you'llencounteraTypeError.Thisisduetothearraymodule'sstricttypeenforcement,whichrequiresallelementstobeofthesametypeasspecifiedbythetypecode.Forperformancereasons,arraysaremoreefficientthanl

Python标准库的哪一部分是:列表或数组?Python标准库的哪一部分是:列表或数组?Apr 27, 2025 am 12:03 AM

pythonlistsarepartofthestAndArdLibrary,herilearRaysarenot.listsarebuilt-In,多功能,和Rused ForStoringCollections,而EasaraySaraySaraySaraysaraySaraySaraysaraySaraysarrayModuleandleandleandlesscommonlyusedDduetolimitedFunctionalityFunctionalityFunctionality。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器