1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > windows popen 获取不到输出_彻底明白os.system os.popen subprocess.popen的用法和区别...

windows popen 获取不到输出_彻底明白os.system os.popen subprocess.popen的用法和区别...

时间:2018-06-23 23:51:01

相关推荐

windows popen 获取不到输出_彻底明白os.system os.popen subprocess.popen的用法和区别...

Hello,大家好,沉寂许久,我又来了,这次给大家分享的就是上述三个方法的使用范围和区别,不熟悉的可以在这个地方画一个圆满的句号了。

os.system

首先来看这个函数的文档说明

是说是在一个子shell中执行命令, 也即相当于执行手动在CMD窗口输入的命令

import osprint(os.system('cd ..')) # 结果会打印出来0, 表示命令执行成功, 否则表示执行失败,例如执行print(os.system('mkdir new_folder')) # 执行第一次, 结果是0 第二次返回值是子目录或者文件 new_folder已经存在,#目前来说,我在使用的时候没有出现太多的莫名其妙的错误,但是有大神说不建议用这个模块,由下面两种代替。

os.popen

popen() 创建一个管道,通过fork一个子进程,然后该子进程执行命令。返回值在标准IO流中,该管道用于父子进程间通信。父进程要么从管道读信息,要么向管道写信息,至于是读还是写取决于父进程调用popen时传递的参数(w或r)其返回值是file read的对象,对其进行读取read()操作可以看到执行的输出

import osprint(os.popen('mkdir new_folder').read()) # 创建成功的话没有任何返回值, 但是如果已经存在的话, 子目录或者文件 new_folder已经存在,print(os.popen('ipconfig').read()) # 跟在cmd 窗口敲该命令结果一样, 显示该计算机的ip详情信息 不添加read的话,

subprocess.Popen

该模块是在2.4版本中新增的,官方文档描述可以用来替换以下函数:os.system、os.spawn、os.popen、popen2,它的目的是启动一个新进程并且与之进行通信,最常用的定义是使用类Popen(), 它可以创建进程,并且与进程进行复杂的交互,一个比较明显的缺点是它是一个阻塞的方法,如果运行的CMD命令时产生的内容非常多,函数就是会非常容易阻塞,另外一点,它也不会打印出CMD的执行信息

import subprocesssubprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)# 其中args值的是需要传入的要执行的程序路径(字符串),如果是列表的话,第一项是程序的路径,后面的参数是执行该程序所需要的参数,这个与popen一致。# 下面是各个参数的详解# bufsize 指定缓冲,0 无缓冲, 1 行缓冲 其他正值 缓冲区大小 负值 采用的默认系统缓冲(一般是全缓冲)# executable: 用于指定可执行程序。一般情况下我们通过args参数来设置所要运行的程序。如果将参数shell设为 True,executable将指定程序使用的shell。在windows平台下,默认的shell由COMSPEC环境变量来指定。# stdin stdout stderr 三者是成程序的标准输入、标准输出、错误句柄。可以赋值为None(没有任何重定向,继承父进程)、PIPE(创建管道)、文件对象、文件描述符(整数)等,其中stderr还是可以设置成STDOUT,# preexc_fn:只是在Unix下生效,用于指定一个可执行对象,它将在子进程运行之前被调用。# close_sfs:在windows平台下,如果如果该参数被设置成True,那么新创建的子进程将不会继承父进程的输入输出错误管道,我们不能将该函数设置为True同时重定向子进程的标准输入输出与错误。# shell:在unix下就是相当于在args前面添加了"/bin/sh /c" 在windows下相当于添加了"cmd.exe /c"# cmd:设置子进程的工作目录# env:字典类型,用于指定子进程的环境变量,如果env=None,那么子进程的环境变量将从父进程中继承# Universal_newlines:不同操作系统下,文本的换行符是不一样的。如:windows下用'/r/n'表示换,而Linux下用 '/n'。如果将此参数设置为True,Python统一把这些换行符当作’/n’来处理。#参数startupinfo与createionflags只在windows下有效,它们将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等。

下面解释一下缓冲区

概念:它的本质是一块存储区域。

为什么要产生?

这就涉及到了CPU与硬件通信问题,我们都知道,CPU的处理速度是很快的,但是存储设备以及其他的I/O(键盘输入文字)操作却是很慢的,所以为了保证CPU与低速部件通信吻合住,就需要先将CPU的处理结果的输出暂时存储到某处,当达到某个阈值的时候,再去调用CPU进行统一处理,这样就会让CPU变得高效起来,因为我们的文字输入以及存储到硬盘对于CPU来说是很慢的,CPU不能老是等着我们,因此引入缓冲区

缓冲区的分类:

可以分为全缓冲、行缓冲以及无缓冲全缓冲:缓存在缓冲区的内容快要达到缓冲区容量上限的时候。才去写入磁盘或者调用fflush才能写入到磁盘,那么对于缓冲区没满或者没有手动刷新缓存,缓冲区的内容是不会写入到磁盘的。行缓冲:我们的标准输入、输出都是采用的行缓存,也即遇到换行符的时候,才会将缓存区的东西写入到磁盘。无缓冲:有的时候,希望一些内容在第一时间写入磁盘或者显示出来,比如显示错误信息的时候,典型的例子就是标准出错信息,它就是直接显示出错信息,而不会先放入缓存。需要知道的是,在缓冲区满了、程序结束的时候、手动调用fflush的时候,缓冲区才会得到刷新并且写入到磁盘。

所以总的来说,最后一个可以说能替代前两项的,

os.system可以用subprocess.call来替代,os.popen可以使用subprocess。Popen来替代。

附一段代码,使用subprocess从运行的子进程中实时获取输出

首先是模拟标准输出和标准错误输出的子程序sub_process.py

import sysimport timefor i in range(5): sys.stdout.write('Processing {}\n'.format(i)) time.sleep(1)for i in range(5): sys.stderr.write('Error {}\n'.format(i)) time.sleep(1)

接着是驱动子程序的主程序 main_process.py

import shleximport subprocessif __name__ == '__main__': shell_cmd = 'python sub_process.py' cmd = shlex.split(shell_cmd) p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while p.poll() is None: line = p.stdout.readline() line = line.strip() if line: print('Subprogram output: [{}]'.format(line)) if p.returncode == 0: print('Subprogram success') else:print('Subprogramfailed')

通过指定stderr=subprocess.STDOUT,将标准错误重定向到标准输出,期待的结果是每隔一秒获得一条信息,但是实际上确实间隔了10秒一次性输出了出来,这就是缓冲区的概念,它不会立即输出,会做缓存,知道缓存满或者手动刷新或者函数执行结束才会输出,想要看到实时输出的效果需要手动刷新,即

import sysimport timefor i in range(5): sys.stdout.write('Processing {}\n'.format(i)) sys.stdout.flush() time.sleep(1)for i in range(5): sys.stderr.write('Error {}\n'.format(i)) sys.stderr.flush()time.sleep(1)

再去执行主进程函数就会出现预期的效果。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。