精华内容
下载资源
问答
  • popen
    2021-09-24 16:12:33
    更多相关内容
  • popen使用方法示例

    2022-03-28 17:52:37
    popen使用方法示例,代码中调用了popen函数,同时封装函数接口供大家调用。
  • 那么我们在python3中使用os.popen()出错该怎么办?本篇文章小编同样以错误的操作方法为大家进行讲解,一起找寻不对的地方吧。 在当前 desktop 目录下,有如下内容: desktop $ls client.py server.py 中文测试 ...
  • 这里记录一下popen()接受命令返回值及处理,我想要的值是docker的ID $ docker ps -q 2d3586a30e7e 03f1ca1331c7 但是使用python调用的时候没法直接得到这个结果,所以想要获取这个数据  #导入os这个模块 In [8]:...
  • 问题产生描述 ... p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) p.wait() # 从标准输出读出shell命令的输出结果 #rt = p.stdout.read().decode() #
  • popen() —— 代表“管道打开” —— 是许多 Unix 版本中提供的非常有用的系统调用。 它运行一个作为字符串传入的命令,然后返回一个文件句柄,这样父进程就可以像文件一样读取或写入该进程; 以这种方式传递的数据...
  • 0x00 前言 这种命令行注入在pwn中出现的比较少,所以记录分享一下。 0x01 命令行注入介绍 熟悉web安全的话就知道,如果对特殊字符过滤不当,会引发sql注入或者xss等安全漏洞。其中,命令行注入较为严重,因为可以...
  • popen包在 python 中提供了一个简单的类似 shell 的语法来运行外部命令。 特征: 链接(又名管道)为Sh('ls') | 'sort' Sh('ls') | 'sort' 将标准错误重定向到标准输出作为Sh('make').include_stderr | 'wc' Sh...
  • 参考popen, pclose源码进行了修改 第一次的问题已解决 如下图 #include #include #include #include #include #include #include #include #include #include #include #include #include #define SHELL /bin/bash...
  • 我就废话不多说了,直接上代码吧! import subprocess ... ex = subprocess.Popen(com, stdout=subprocess.PIPE, shell=True) ...以上这篇python Popen 获取输出,等待运行完成示例就是小编分享给大家的全部内容了,希望
  • pclose是阻塞函数,一般情况下,如果使用popen执行一些命令时,如果需要读取一部分信息,此时直接调用pclose函数,会阻塞,如果想不阻塞,需要自己实现pclose函数,目前给出经过测试的自己实现的my_popen
  • subprocess意在替代其他几个老的模块或者函数,比如:os.system os.spawn* os.popen* popen2.* commands.* 一、subprocess.Popen subprocess模块定义了一个类: Popen class subprocess.Popen( args, bufsize=0, ...
  • 1.1 函数原型: 复制代码 代码如下:#include <stdio>FILE *popen(const char *command,const char *open_mode); 1.2 说明 popen函数允许一个程序将另一个程序作为新进程启动,并可以传递数据给它或者通过它接收数据...
  • Linux系统中popen函数的缺陷与改造方案.pdf
  • popen()函数通过创建一个管道,调用fork()产生一个子进程,执行一个shell以运行命令来开启一个进程。这篇文章重点给大家介绍Linux中popen函数的作用,感兴趣的朋友一起看看吧
  • 最近在做web服务器端处理。刚好用到要在服务器端调用popen函数查询相关命令,并上传到前端。所以在服务器端做的查询ip,mask等的测试代码。在linux下编译运行即可得到需要的值。代码简单。
  • popen_timeout.py

    2019-09-18 10:08:02
    在python开发中经常要执行一些外部的小程序,可恶的是这小程序经常阻塞了,我们在python中只看到python程序不动了还不知道程序跑到哪里。
  • 重写系统提供的system和popen函数,在fork之后关闭所有的从3到最大的文件描述符
  • python 打印信息重定向 GUI界面 ,PyQt5实时显示调用外部程序的实时输出显示,subprocess.Popen stdout输出重定向,备注详细!
  • popen使用方法及场景

    2022-05-11 13:10:44
    1. popen的应用场景 popen应用于执行shell命令,并读取此命令的返值,或者与执行的命令进行交互。 2. popen的实现 popen()函数通过创建一个管道,调用fork()产生一个子进程,执行一个shell以运行命令来开启一个...

    1. popen的应用场景

    popen应用于执行shell命令,并读取此命令的返值,或者与执行的命令进行交互。

    2. popen的实现

    popen()函数通过创建一个管道,调用fork()产生一个子进程,执行一个shell以运行命令来开启一个进程。可以通过这个管道执行标准输入输出操作。这个管道必须由pclose()函数关闭,必须由pclose()函数关闭,必须由pclose()函数关闭,而不是fclose()函数(若使用fclose则会产生僵尸进程)。pclose()函数关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态。如果shell不能被执行,则pclose()返回的终止状态与shell已执行exit一样。

    type参数只能是读或者写中的一种,得到的返回值(标准I/O流)也具有和type相应的只读或只写类型。如果type是"r"则文件指针连接到command的标准输出;如果type是"w"则文件指针连接到command的标准输入。

    command参数是一个指向以NULL结束的shell命令字符串的指针。这行命令将被传到bin/sh并使用-c标志,shell将执行这个命令。

    popen()的返回值是个标准I/O流,必须由pclose来终止。前面提到这个流是单向的(只能用于读或写)。向这个流写内容相当于写入该命令的标准输入,命令的标准输出和调用popen()的进程相同;与之相反的,从流中读数据相当于读取命令的标准输出,命令的标准输入和调用popen()的进程相同。

    返回值

    如果调用fork()或pipe()失败,或者不能分配内存将返回NULL,否则返回标准I/O流。popen()没有为内存分配失败设置errno值。如果调用fork()或pipe()时出现错误,errno被设为相应的错误类型。如果type参数不合法,errno将返回EINVAL。

     
    
    1. FILE *popen(const char *command, const char *type);

    2. int pclose(FILE *stream);

    3. pclose操作

    pclose()函数会闭标准I/0流,等待子进程结束,然后返回shell终止状态。如果不执行,则pclose()返回终止状态就是shell的exit状态。

    源码附上:

     
    
    1. /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>

    2. * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>

    3. *

    4. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.

    5. *

    6. * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.

    7. */

    8. /* Jan 1, 2004

    9. *

    10. * Rewrite popen for SUSv3 compliance.

    11. * Added a list of popen()'d to store pids and use waitpid() in pclose().

    12. * Loop on waitpid() failure due to EINTR as required.

    13. * Close parent's popen()'d FILEs in the {v}fork()'d child.

    14. * Fix failure exit code for failed execve().

    15. */

    16. #include <stdio.h>

    17. #include <stdlib.h>

    18. #include <errno.h>

    19. #include <unistd.h>

    20. #include <sys/wait.h>

    21. #include <bits/uClibc_mutex.h>

    22. #ifdef __UCLIBC_MJN3_ONLY__

    23. #warning "hmm... susv3 says Pipe streams are byte-oriented."

    24. #endif /* __UCLIBC_MJN3_ONLY__ */

    25. /* uClinux-2.0 has vfork, but Linux 2.0 doesn't */

    26. #include <sys/syscall.h>

    27. #if ! defined __NR_vfork

    28. # define vfork fork

    29. # define VFORK_LOCK ((void) 0)

    30. # define VFORK_UNLOCK ((void) 0)

    31. #endif

    32. #ifndef VFORK_LOCK

    33. __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);

    34. # define VFORK_LOCK __UCLIBC_MUTEX_LOCK(mylock)

    35. # define VFORK_UNLOCK __UCLIBC_MUTEX_UNLOCK(mylock)

    36. #endif

    37. struct popen_list_item {

    38. struct popen_list_item *next;

    39. FILE *f;

    40. pid_t pid;

    41. };

    42. static struct popen_list_item *popen_list /* = NULL (bss initialized) */;

    43. FILE *popen(const char *command, const char *modes)

    44. {

    45. FILE *fp;

    46. struct popen_list_item *pi;

    47. struct popen_list_item *po;

    48. int pipe_fd[2];

    49. int parent_fd;

    50. int child_fd;

    51. int child_writing; /* Doubles as the desired child fildes. */

    52. pid_t pid;

    53. child_writing = 0; /* Assume child is writing. */

    54. if (modes[0] != 'w') { /* Parent not writing... */

    55. ++child_writing; /* so child must be writing. */

    56. if (modes[0] != 'r') { /* Oops! Parent not reading either! */

    57. __set_errno(EINVAL);

    58. goto RET_NULL;

    59. }

    60. }

    61. if (!(pi = malloc(sizeof(struct popen_list_item)))) {

    62. goto RET_NULL;

    63. }

    64. // 打开一个pipe,管道是单向。故数据流只能单向流动。

    65. if (pipe(pipe_fd)) {

    66. goto FREE_PI;

    67. }

    68. //下面两个描述符就是管道的两端的描述,一个为读一个为写。

    69. child_fd = pipe_fd[child_writing];

    70. parent_fd = pipe_fd[1-child_writing];

    71. //fdopen就是打开一个描述,fd相同模式或者字集的方式打开。意思就是把一个已找打开的流与一个文件描述符相关联,且

    72. //这个文件描述是唯一的,这样也就可以保证这个函数接口的可重入性。如果设计的不可重入性,也就没必要再做一次fdopen了。

    73. if (!(fp = fdopen(parent_fd, modes))) {

    74. close(parent_fd);

    75. close(child_fd);

    76. goto FREE_PI;

    77. }

    78. VFORK_LOCK;

    79. //再这里创建一个子进程,然后执行 shell命令。这里最重的两步就是用pipe的两个描述替换标准输入或者输出。

    80. if ((pid = vfork()) == 0) { /* Child of vfork... */

    81. close(parent_fd);

    82. if (child_fd != child_writing) {

    83. dup2(child_fd, child_writing); //用child_fd来代替标准输入或输出。

    84. close(child_fd);

    85. }

    86. /* SUSv3 requires that any previously popen()'d streams in the

    87. * parent shall be closed in the child. */

    88. //关闭不必要的资源。

    89. for (po = popen_list ; po ; po = po->next) {

    90. close(po->f->__filedes);

    91. }

    92. //执行exec shell,这个时候标准输入/输出就变为pipe管道的一端了。

    93. //这里只能实现单向的功能。要么读要么写。

    94. execl("/bin/sh", "sh", "-c", command, (char *)0);

    95. /* SUSv3 mandates an exit code of 127 for the child if the

    96. * command interpreter can not be invoked. */

    97. _exit(127);

    98. }

    99. VFORK_UNLOCK;

    100. /* We need to close the child filedes whether vfork failed or

    101. * it succeeded and we're in the parent. */

    102. close(child_fd);

    103. //将当前的信息保存到全局链表。为了是pclose可以找到对的子进程与通信文件描述。

    104. if (pid > 0) { /* Parent of vfork... */

    105. pi->pid = pid;

    106. pi->f = fp;

    107. VFORK_LOCK;

    108. pi->next = popen_list;

    109. popen_list = pi;

    110. VFORK_UNLOCK;

    111. return fp;

    112. }

    113. /* If we get here, vfork failed. */

    114. fclose(fp); /* Will close parent_fd. */

    115. FREE_PI:

    116. free(pi);

    117. RET_NULL:

    118. return NULL;

    119. }

    120. #warning is pclose correct wrt the new mutex semantics?

    121. int pclose(FILE *stream)

    122. {

    123. struct popen_list_item *p;

    124. int stat;

    125. pid_t pid;

    126. /* First, find the list entry corresponding to stream and remove it

    127. * from the list. Set p to the list item (NULL if not found). */

    128. VFORK_LOCK;

    129. if ((p = popen_list) != NULL) {

    130. if (p->f == stream) {// 找到stream对应的popen结点。

    131. popen_list = p->next;

    132. } else {

    133. struct popen_list_item *t;

    134. do {

    135. t = p;

    136. if (!(p = t->next)) {

    137. __set_errno(EINVAL); /* Not required by SUSv3. */

    138. break;

    139. }

    140. if (p->f == stream) {

    141. t->next = p->next;

    142. break;

    143. }

    144. } while (1);

    145. }

    146. }

    147. VFORK_UNLOCK;

    148. if (p) {

    149. pid = p->pid; /* Save the pid we need */

    150. free(p); /* and free the list item. */

    151. fclose(stream); /* The SUSv3 example code ignores the return. */

    152. /* SUSv3 specificly requires that pclose not return before the child

    153. * terminates, in order to disallow pclose from returning on EINTR. */

    154. do {

    155. if (waitpid(pid, &stat, 0) >= 0) { //等待子进程返回。获取返回值。

    156. return stat;

    157. }

    158. if (errno != EINTR) {

    159. break;

    160. }

    161. } while (1);

    162. }

    163. return -1;

    164. }

    举例附上:

     
    
    1. #include <stdio.h>

    2. #include <string.h>

    3. int main()

    4. {

    5. FILE *fp = NULL;

    6. char buf[1024] = "";

    7. fp = popen("ls -al", "r");

    8. if(fp == NULL)

    9. {

    10. perror("popen error\n");

    11. return -1;

    12. }

    13. while(fgets(buf, sizeof(buf), fp) != 0)

    14. {

    15. printf("%s\n", buf);

    16. memset(buf, 0x0, sizeof(buf));

    17. }

    18. pclose(fp);

    19. return 0;

    20. }

    展开全文
  • 从python2.4版本开始,可以用subprocess这个模块来产生子进程,并连接到子进程的标准输入/输出/错误中去,还可以得到子进程的...subprocess意在替代其他几个老的模块或者函数,比如:os.system os.spawnos.popen**...

    从python2.4版本开始,可以用subprocess这个模块来产生子进程,并连接到子进程的标准输入/输出/错误中去,还可以得到子进程的返回值。
    subprocess意在替代其他几个老的模块或者函数,比如:os.system os.spawn
    os.popen
    popen2.* commands.*
    **

    一、subprocess.Popen

    subprocess模块定义了一个类: Popen
    class subprocess.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:
    args参数。可以是一个字符串,可以是一个包含程序参数的列表。要执行的程序一般就是这个列表的第一项,或者是字符串本身。
    subprocess.Popen([“cat”,“test.txt”])
    subprocess.Popen(“cat test.txt”)
    这两个之中,后者将不会工作。因为如果是一个字符串的话,必须是程序的路径才可以。(考虑unix的api函数exec,接受的是字符串
    列表)
    但是下面的可以工作
    subprocess.Popen(“cat test.txt”, shell=True)
    这是因为它相当于
    subprocess.Popen([“/bin/sh”, “-c”, “cat test.txt”])
    在*nix下,当shell=False(默认)时,Popen使用os.execvp()来执行子程序。args一般要是一个【列表】。如果args是个字符串的
    话,会被当做是可执行文件的路径,这样就不能传入任何参数了。

    注意:
    shlex.split()可以被用于序列化复杂的命令参数,比如:

    shlex.split(‘ls ps top grep pkill’)
    [‘ls’, ‘ps’, ‘top’, ‘grep’, ‘pkill’]
    import shlex, subprocess
    command_line = raw_input()
    /bin/cat -input test.txt -output “diege.txt” -cmd “echo ‘MONEY’”]
    p=subprocess.Popen(args)
    可以看到,空格分隔的选项(如-input)和参数(如test.txt)会被分割为列表里独立的项,但引号里的或者转义过的空格不在此列
    。这也有点像大多数shell的行为。

    在*nix下,当shell=True时,如果arg是个字符串,就使用shell来解释执行这个字符串。如果args是个列表,则第一项被视为命令,
    其余的都视为是给shell本身的参数。也就是说,等效于:
    subprocess.Popen([‘/bin/sh’, ‘-c’, args[0], args[1], …])

    在Windows下,下面的却又是可以工作的
    subprocess.Popen([“notepad.exe”, “test.txt”])
    subprocess.Popen(“notepad.exe test.txt”)
    这是由于windows下的api函数CreateProcess接受的是一个字符串。即使是列表形式的参数,也需要先合并成字符串再传递给api函数
    subprocess.Popen(“notepad.exe test.txt” shell=True)
    等同于
    subprocess.Popen("cmd.exe /C "+“notepad.exe test.txt” shell=True)

    bufsize参数:
    如果指定了bufsize参数作用就和内建函数open()一样:0表示不缓冲,1表示行缓冲,其他正数表示近似的缓冲区字节数,负数表
    示使用系统默认值。默认是0。

    executable参数:
    指定要执行的程序。它很少会被用到:一般程序可以由args 参数指定。如果shell=True ,executable
    可以用于指定用哪个shell来执行(比如bash、csh、zsh等)。*nix下,默认是 /bin/sh ,windows下,就是环境变量 COMSPEC
    的值。windows下,只有当你要执行的命令确实是shell内建命令(比如dir ,copy 等)时,你才需要指定shell=True
    ,而当你要执行一个基于命令行的批处理脚本的时候,不需要指定此项。

    stdin stdout和stderr:
    stdin stdout和stderr,分别表示子程序的标准输入、标准输出和标准错误。可选的值有PIPE或者一个有效的文件描述符(其实是个正
    整数)或者一个文件对象,还有None。如果是PIPE,则表示需要创建一个新的管道,如果是None
    ,不会做任何重定向工作,子进程的文件描述符会继承父进程的。另外,stderr的值还可以是STDOUT
    ,表示子进程的标准错误也输出到标准输出。

    preexec_fn参数:
    如果把preexec_fn设置为一个可调用的对象(比如函数),就会在子进程被执行前被调用。(仅限*nix)

    close_fds参数:
    如果把close_fds设置成True,*nix下会在开子进程前把除了0、1、2以外的文件描述符都先关闭。在 Windows下也不会继承其他文件描述符。

    shell参数:
    如果把shell设置成True,指定的命令会在shell里解释执行。

    cwd参数:
    如果cwd不是None,则会把cwd做为子程序的当前目录。注意,并不会把该目录做为可执行文件的搜索目录,所以不要把程序文件所在
    目录设置为cwd 。

    env参数:
    如果env不是None,则子程序的环境变量由env的值来设置,而不是默认那样继承父进程的环境变量。注意,即使你只在env里定义了
    某一个环境变量的值,也会阻止子程序得到其
    他的父进程的环境变量(也就是说,如果env里只有1项,那么子进程的环境变量就只有1个了)。例如:

    subprocess.Popen(‘env’, env={‘test’:‘123’, ‘testtext’:‘zzz’})
    test=123
    <subprocess.Popen object at 0x2870ad2c>
    testtext=zzz

    universal_newlines参数:
    如果把universal_newlines 设置成True,则子进程的stdout和stderr被视为文本对象,并且不管是*nix的行结束符(‘/n’
    ),还是老mac格式的行结束符(‘/r’ ),还是windows 格式的行结束符(‘/r/n’ )都将被视为 ‘/n’ 。

    startupinfo和creationflags参数:
    如果指定了startupinfo和creationflags,将会被传递给后面的CreateProcess()函数,用于指定子程序的各种其他属性,比如主窗口样式或者是
    子进程的优先级等。(仅限Windows)

    二、subprocess.PIPE

    subprocess.PIPE
    一个可以被用于Popen的stdin 、stdout 和stderr 3个参数的特输值,表示需要创建一个新的管道。
    subprocess.STDOUT
    一个可以被用于Popen的stderr参数的输出值,表示子程序的标准错误汇合到标准输出。
    实例:

    p=subprocess.Popen("df -h",shell=True,stdout=subprocess.PIPE)
    out=p.stdout.readlines()
    

    out=>
    [b’Filesystem Size Used Avail Capacity Mounted on\n’, b’/dev/ad0s1a 713M 313M 343M 48% /\n’, b’devfs 1.0K 1.0K 0B 100% /dev\n’, b’/dev/ad0s1e 514M 2.1M 471M 0% /tmp\n’, b’/dev/ad0s1f 4.3G 2.5G 1.4G 64% /usr\n’, b’/dev/ad0s1d 2.0G 121M 1.7G 6% /var\n’

     for line in out:
          print line.strip()
    


    Filesystem Size Used Avail Capacity Mounted on
    /dev/ad0s1a 713M 313M 343M 48% /
    devfs 1.0K 1.0K 0B 100% /dev
    /dev/ad0s1e 514M 2.1M 471M 0% /tmp
    /dev/ad0s1f 4.3G 2.5G 1.4G 64% /usr
    /dev/ad0s1d 2.0G 121M 1.7G 6% /var
    stdout可以使用read(),readline(),readlines()等方法

    三、方便的函数
    1、subprocess.call
    subprocess.call (*popenargs , *kwargs )
    执行命令,并等待命令结束,再返回子进程的返回值。参数同Popen,查看/usr/lib/python2.7/subprocess.py
    去掉文档,其实是这样的:

    def call(popenargs, *kwargs):
    	return Popen(popenargs, **kwargs).wait()
    subprocess.call('ifconfig',shell=True)
    

    2、subprocess.check_call
    subprocess.check_call (*popenargs , *kwargs )
    执行上面的call命令,并检查返回值,如果子进程返回非0,则会抛出CalledProcessError异常,这个异常会有个returncode
    属性,记录子进程的返回值。

    def check_call(popenargs, *kwargs):
    	retcode = call(popenargs, *kwargs)
    	if retcode:
    		cmd = kwargs.get("args")
    	raise CalledProcessError(retcode, cmd)
    	return 0
     subprocess.check_call('ifconfig')
     subprocess.call('noifconfig')
    

    Traceback (most recent call last):
    File “”, line 1, in
    File “/usr/local/lib/python2.7/subprocess.py”, line 493, in call
    return Popen(popenargs, **kwargs).wait()
    File “/usr/local/lib/python2.7/subprocess.py”, line 679, in init
    errread, errwrite)
    File “/usr/local/lib/python2.7/subprocess.py”, line 1228, in _execute_child
    raise child_exception
    OSError: [Errno 2] No such file or directory

    异常子进程里抛出的异常,会在父进程中再次抛出。并且,异常会有个叫child_traceback的额外属性,这是个包含子进程错误traceback
    信息的字符串。遇到最多的错误回是 OSError,比如执行了一个并不存在的子程序就会产生OSError。另外,如果使用错误的参数调用Popen
    ,会抛出ValueError。当子程序返回非0时,check_call()还会产生CalledProcessError 异常。
    安全性
    不像其他的popen函数,本函数不会调用/bin/sh来解释命令,也就是说,命令中的每一个字符都会被安全地传递到子进程里。

    3、check_output
    check_output()执行程序,并返回其标准输出.

    def check_output(*popenargs, *kwargs):
    	process = Popen(popenargs, stdout=PIPE, **kwargs)
    	output, unused_err = process.communicate()
    	retcode = process.poll()
    	if retcode:
    		cmd = kwargs.get("args")
    	raise CalledProcessError(retcode, cmd, output=output)
    	return output
    	
    p=subprocess.check_output('ifconfig')
    
    

    结果是所有行/n分割的一个字符串
    可以直接print出来
    这里开始

    4、Popen对象

    image
    产生对象

    p=subprocess.Popen("df -h",shell=True,stdout=subprocess.PIPE)
    

    Popen对象有以下方法:

    Popen.poll()

    检查子进程是否已结束,设置并返回returncode属性。

    p.poll()
    Popen.wait()
    

    等待子进程结束,设置并返回returncode属性。
    p.wait()

    注意: 如果子进程输出了大量数据到stdout或者stderr的管道,并达到了系统pipe的缓存大小的话,
    子进程会等待父进程读取管道,而父进程此时正wait着的话,将会产生传说中的死锁,后果是非常严重滴。建议使用
    communicate()来避免这种情况的发生。

    Popen.communicate(input=None)
    和子进程交互:发送数据到stdin,并从stdout和stderr读数据,直到收到EOF。等待子进程结束。可选的input如有有的话,要为字符串类型。
    此函数返回一个元组: (stdoutdata , stderrdata ) 。
    注意,要给子进程的stdin发送数据,则Popen的时候,stdin要为PIPE;同理,要可以接收数据的话,stdout或者stderr也要为PIPE。

    p1=subprocess.Popen('cat /etc/passwd',shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
    p2=subprocess.Popen('grep 0:0',shell=True,stdin=p1.stdout,stdout=subprocess.PIPE)
    
    p.communicate()
    

    注意:读到的数据会被缓存在内存里,所以数据量非常大的时候要小心了。

    Popen.send_signal(signal)
    给子进程发送signal信号。
    注意:windows下目前只支持发送SIGTERM,等效于下面的terminate() 。

    Popen.terminate()
    停止子进程。Posix下是发送SIGTERM信号。windows下是调用TerminateProcess()这个API。

    Popen.kill()
    杀死子进程。Posix下是发送SIGKILL信号。windows下和terminate() 无异。

    Popen.stdin
    如果stdin 参数是PIPE,此属性就是一个文件对象,否则为None 。

    Popen.stdout
    如果stdout参数是PIPE,此属性就是一个文件对象,否则为None 。

    Popen.stderr
    如果stderr 参数是PIPE,此属性就是一个文件对象,否则为None 。

    Popen.pid
    子进程的进程号。注意,如果shell 参数为True,这属性指的是子shell的进程号。

    Popen.returncode
    子程序的返回值,由poll()或者wait()设置,间接地也由communicate()设置。
    如果为None,表示子进程还没终止。
    如果为负数-N的话,表示子进程被N号信号终止。(仅限*nux)

    用subprocess来代替其他函数

    都可以用subprocess来完成,我们假定是用 “from subprocess import *” 来导入模块的:

    代替shell命令:
    p=ls -l
    等效于
    p=Popen([‘ls’,‘-l’],stdout=PIPE).communicate()[0]

    代替shell管道:
    p=dmesg | grep cpu
    等效于
    p1=Popen([‘dmesg’],stdout=PIPE)
    p2=Popen([‘grep’,‘cpu’],stdin=p1.stdout,stdout=PIPE)
    output = p2.communicate()[0]

     p1=subprocess.Popen('cat /etc/passwd',shell=True,stdout=subprocess.PIPE)
     p2=subprocess.Popen('grep 0:0',shell=True,stdin=p1.stdout,stdout=subprocess.PIPE)
     p3=subprocess.Popen("cut -d ':' -f 7",shell=True,stdin=p2.stdout,stdout=subprocess.PIPE)
     print p3.stdout.read()
    

    代替os.system()
    ls -l => os.system(‘ls ‘+’-l’)
    这个是一个返回状态
    等效于
    p=Popen(‘ls -l’, shell=True)

    注意:
    通常并不需要用shell来调用程序。用subprocess可以更方便地得到子程序的返回值。
    其实,更真实的替换是:

    try:
    retcode = call(“mycmd” + ” myarg”, shell=True)
    if retcode < 0:
    print >>sys.stderr, “Child was terminated by signal”, -retcode
    else:
    print >>sys.stderr, “Child returned”, retcode
    except OSError, e:
    print >>sys.stderr, “Execution failed:”, e

    代替os.spawn系列
    P_NOWAIT的例子
    pid = os.spawnlp(os.P_NOWAIT, “/bin/mycmd”, “mycmd”, “myarg”)
    等效于
    pid = Popen([“/bin/mycmd”, “myarg”]).pid

    P_WAIT的例子

    retcode = os.spawnlp(os.P_WAIT, “/bin/mycmd”, “mycmd”, “myarg”)
    等效于
    retcode = call([“/bin/mycmd”, “myarg”])

    返回值处理:

    pipe = os.popen(“cmd”, ‘w’)

    rc = pipe.close()
    if rc != None and rc % 256:
    print “There were some errors”
    等效于
    process = Popen(“cmd”, ‘w’, shell=True, stdin=PIPE)
    
    process.stdin.close()
    if process.wait() != 0:
    print “There were some errors”
    
    展开全文
  • subprocess.Popen()详解

    千次阅读 2021-01-28 18:05:45
    一、subprocess.Popensubprocess模块定义了一个类: Popenclass subprocess.Popen( args,bufsize=0,executable=None,stdin=None,stdout=None,stderr=None,preexec_fn=None,close_fds=False,shell=False,cwd=None,env...

    一、subprocess.Popen

    subprocess模块定义了一个类: Popen

    class subprocess.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:

    args参数。可以是一个字符串,可以是一个包含程序参数的列表。要执行的程序一般就是这个列表的第一项,或者是字符串本身。

    subprocess.Popen(["cat","test.txt"])

    subprocess.Popen("cat test.txt")

    这两个之中,后者将不会工作。因为如果是一个字符串的话,必须是程序的路径才可以。(考虑unix的api函数exec,接受的是字符串

    列表)

    但是下面的可以工作

    subprocess.Popen("cat test.txt", shell=True)

    这是因为它相当于

    subprocess.Popen(["/bin/sh", "-c", "cat test.txt"])

    在*nix下,当shell=False(默认)时,Popen使用os.execvp()来执行子程序。args一般要是一个【列表】。如果args是个字符串的

    话,会被当做是可执行文件的路径,这样就不能传入任何参数了。

    注意:

    shlex.split()可以被用于序列化复杂的命令参数,比如:

    >>> shlex.split('ls ps top grep pkill')

    ['ls', 'ps', 'top', 'grep', 'pkill']

    >>>import shlex, subprocess

    >>>command_line = raw_input()

    /bin/cat -input test.txt -output "diege.txt" -cmd "echo '$MONEY'"

    >>>args = shlex.split(command_line)

    >>> print args

    ['/bin/cat', '-input', 'test.txt', '-output', 'diege.txt', '-cmd', "echo '$MONEY'"]

    >>>p=subprocess.Popen(args)

    可以看到,空格分隔的选项(如-input)和参数(如test.txt)会被分割为列表里独立的项,但引号里的或者转义过的空格不在此列

    。这也有点像大多数shell的行为。

    在*nix下,当shell=True时,如果arg是个字符串,就使用shell来解释执行这个字符串。如果args是个列表,则第一项被视为命令,

    其余的都视为是给shell本身的参数。也就是说,等效于:

    subprocess.Popen(['/bin/sh', '-c', args[0], args[1], ...])

    在Windows下,下面的却又是可以工作的

    subprocess.Popen(["notepad.exe", "test.txt"])

    subprocess.Popen("notepad.exe test.txt")

    这是由于windows下的api函数CreateProcess接受的是一个字符串。即使是列表形式的参数,也需要先合并成字符串再传递给api函数

    subprocess.Popen("notepad.exe test.txt" shell=True)

    等同于

    subprocess.Popen("cmd.exe /C "+"notepad.exe test.txt" shell=True)

    bufsize参数:

    如果指定了bufsize参数作用就和内建函数open()一样:0表示不缓冲,1表示行缓冲,其他正数表示近似的缓冲区字节数,负数表

    示使用系统默认值。默认是0。

    executable参数:

    指定要执行的程序。它很少会被用到:一般程序可以由args 参数指定。如果shell=True ,executable

    可以用于指定用哪个shell来执行(比如bash、csh、zsh等)。*nix下,默认是 /bin/sh ,windows下,就是环境变量 COMSPEC

    的值。windows下,只有当你要执行的命令确实是shell内建命令(比如dir ,copy 等)时,你才需要指定shell=True

    ,而当你要执行一个基于命令行的批处理脚本的时候,不需要指定此项。

    stdin stdout和stderr:

    stdin stdout和stderr,分别表示子程序的标准输入、标准输出和标准错误。可选的值有PIPE或者一个有效的文件描述符(其实是个正

    整数)或者一个文件对象,还有None。如果是PIPE,则表示需要创建一个新的管道,如果是None

    ,不会做任何重定向工作,子进程的文件描述符会继承父进程的。另外,stderr的值还可以是STDOUT

    ,表示子进程的标准错误也输出到标准输出。

    preexec_fn参数:

    如果把preexec_fn设置为一个可调用的对象(比如函数),就会在子进程被执行前被调用。(仅限*nix)

    close_fds参数:

    如果把close_fds设置成True,*nix下会在开子进程前把除了0、1、2以外的文件描述符都先关闭。在 Windows下也不会继承其他文件描述符。

    shell参数:

    如果把shell设置成True,指定的命令会在shell里解释执行。

    cwd参数:

    如果cwd不是None,则会把cwd做为子程序的当前目录。注意,并不会把该目录做为可执行文件的搜索目录,所以不要把程序文件所在

    目录设置为cwd 。

    env参数:

    如果env不是None,则子程序的环境变量由env的值来设置,而不是默认那样继承父进程的环境变量。注意,即使你只在env里定义了

    某一个环境变量的值,也会阻止子程序得到其

    他的父进程的环境变量(也就是说,如果env里只有1项,那么子进程的环境变量就只有1个了)。例如:

    >>> subprocess.Popen('env', env={'test':'123', 'testtext':'zzz'})

    test=123

    testtext=zzz

    universal_newlines参数:

    如果把universal_newlines 设置成True,则子进程的stdout和stderr被视为文本对象,并且不管是*nix的行结束符('/n'

    ),还是老mac格式的行结束符('/r' ),还是windows 格式的行结束符('/r/n' )都将被视为 '/n' 。

    startupinfo和creationflags参数:

    如果指定了startupinfo和creationflags,将会被传递给后面的CreateProcess()函数,用于指定子程序的各种其他属性,比如主窗口样式或者是

    子进程的优先级等。(仅限Windows)

    二、subprocess.PIPE

    subprocess.PIPE

    一个可以被用于Popen的stdin 、stdout 和stderr 3个参数的特输值,表示需要创建一个新的管道。

    subprocess.STDOUT

    一个可以被用于Popen的stderr参数的输出值,表示子程序的标准错误汇合到标准输出。

    实例:

    >>>p=subprocess.Popen("df -h",shell=True,stdout=subprocess.PIPE)

    >>>out=p.stdout.readlines()

    >>>out

    [b'Filesystem     Size    Used   Avail Capacity  Mounted on\n', b'/dev/ad0s1a    713M    313M    343M    48%    /\n', b'devfs          1.0K    1.0K      0B   100%    /dev\n', b'/dev/ad0s1e    514M    2.1M    471M     0%    /tmp\n', b'/dev/ad0s1f    4.3G    2.5G    1.4G    64%    /usr\n', b'/dev/ad0s1d    2.0G    121M    1.7G     6%    /var\n'

    >>> for line in out:

    ...     print line.strip()

    ...

    Filesystem     Size    Used   Avail Capacity  Mounted on

    /dev/ad0s1a    713M    313M    343M    48%    /

    devfs          1.0K    1.0K      0B   100%    /dev

    /dev/ad0s1e    514M    2.1M    471M     0%    /tmp

    /dev/ad0s1f    4.3G    2.5G    1.4G    64%    /usr

    /dev/ad0s1d    2.0G    121M    1.7G     6%    /var

    stdout可以使用read(),readline(),readlines()等方法

    三、方便的函数

    1、subprocess.call

    subprocess.call (*popenargs , **kwargs )

    执行命令,并等待命令结束,再返回子进程的返回值。参数同Popen,查看/usr/lib/python2.7/subprocess.py

    去掉文档,其实是这样的:

    def call(*popenargs, **kwargs):

    return Popen(*popenargs, **kwargs).wait()

    >>> subprocess.call('ifconfig',shell=True)

    2、subprocess.check_call

    subprocess.check_call (*popenargs , **kwargs )

    执行上面的call命令,并检查返回值,如果子进程返回非0,则会抛出CalledProcessError异常,这个异常会有个returncode

    属性,记录子进程的返回值。

    def check_call(*popenargs, **kwargs):

    retcode = call(*popenargs, **kwargs)

    if retcode:

    cmd = kwargs.get("args")

    raise CalledProcessError(retcode, cmd)

    return 0

    >>> subprocess.check_call('ifconfig')

    >>> subprocess.call('noifconfig')

    Traceback (most recent call last):

    File "", line 1, in

    File "/usr/local/lib/python2.7/subprocess.py", line 493, in call

    return Popen(*popenargs, **kwargs).wait()

    File "/usr/local/lib/python2.7/subprocess.py", line 679, in __init__

    errread, errwrite)

    File "/usr/local/lib/python2.7/subprocess.py", line 1228, in _execute_child

    raise child_exception

    OSError: [Errno 2] No such file or directory

    异常子进程里抛出的异常,会在父进程中再次抛出。并且,异常会有个叫child_traceback的额外属性,这是个包含子进程错误traceback

    信息的字符串。遇到最多的错误回是 OSError,比如执行了一个并不存在的子程序就会产生OSError。另外,如果使用错误的参数调用Popen

    ,会抛出ValueError。当子程序返回非0时,check_call()还会产生CalledProcessError 异常。

    安全性

    不像其他的popen函数,本函数不会调用/bin/sh来解释命令,也就是说,命令中的每一个字符都会被安全地传递到子进程里。

    3、check_output

    check_output()执行程序,并返回其标准输出.

    def check_output(*popenargs, **kwargs):

    process = Popen(*popenargs, stdout=PIPE, **kwargs)

    output, unused_err = process.communicate()

    retcode = process.poll()

    if retcode:

    cmd = kwargs.get("args")

    raise CalledProcessError(retcode, cmd, output=output)

    return output

    p=subprocess.check_output('ifconfig')

    结果是所有行/n分割的一个字符串

    可以直接print出来

    这里开始

    4、Popen对象

    产生对象

    p=subprocess.Popen("df -h",shell=True,stdout=subprocess.PIPE)

    >>> dir(p)

    Popen对象有以下方法:

    Popen.poll()

    检查子进程是否已结束,设置并返回returncode属性。

    >>> p.poll()

    0

    Popen.wait()

    等待子进程结束,设置并返回returncode属性。

    >>> p.wait()

    0

    注意: 如果子进程输出了大量数据到stdout或者stderr的管道,并达到了系统pipe的缓存大小的话,

    子进程会等待父进程读取管道,而父进程此时正wait着的话,将会产生传说中的死锁,后果是非常严重滴。建议使用

    communicate() 来避免这种情况的发生。

    Popen.communicate(input=None)

    和子进程交互:发送数据到stdin,并从stdout和stderr读数据,直到收到EOF。等待子进程结束。可选的input如有有的话,要为字符串类型。

    此函数返回一个元组: (stdoutdata , stderrdata ) 。

    注意,要给子进程的stdin发送数据,则Popen的时候,stdin要为PIPE;同理,要可以接收数据的话,stdout或者stderr也要为PIPE。

    p1=subprocess.Popen('cat /etc/passwd',shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE)

    >>> p2=subprocess.Popen('grep 0:0',shell=True,stdin=p1.stdout,stdout=subprocess.PIPE)

    注意:读到的数据会被缓存在内存里,所以数据量非常大的时候要小心了。

    >>> p.communicate()

    (b'Filesystem     Size    Used   Avail Capacity  Mounted on\n/dev/ad0s1a    713M    313M    343M    48%    /\ndevfs          1.0K    1.0K      0B   100%    /dev\n/dev/ad0s1e    514M    2.1M    471M     0%    /tmp\n/dev/ad0s1f    4.3G    2.5G    1.4G    64%    /usr\n/dev/ad0s1d    2.0G    121M    1.7G     6%    /var\n', None)

    Popen.send_signal(signal)

    给子进程发送signal信号。

    注意:windows下目前只支持发送SIGTERM,等效于下面的terminate() 。

    Popen.terminate()

    停止子进程。Posix下是发送SIGTERM信号。windows下是调用TerminateProcess()这个API。

    Popen.kill()

    杀死子进程。Posix下是发送SIGKILL信号。windows下和terminate() 无异。

    Popen.stdin

    如果stdin 参数是PIPE,此属性就是一个文件对象,否则为None 。

    Popen.stdout

    如果stdout参数是PIPE,此属性就是一个文件对象,否则为None 。

    Popen.stderr

    如果stderr 参数是PIPE,此属性就是一个文件对象,否则为None 。

    Popen.pid

    子进程的进程号。注意,如果shell 参数为True,这属性指的是子shell的进程号。

    >>> p.pid

    22303

    Popen.returncode

    子程序的返回值,由poll()或者wait()设置,间接地也由communicate()设置。

    如果为None,表示子进程还没终止。

    如果为负数-N的话,表示子进程被N号信号终止。(仅限*nux)

    用subprocess来代替其他函数

    都可以用subprocess来完成,我们假定是用 “from subprocess import *” 来导入模块的:

    代替shell命令:

    p=`ls -l`

    等效于

    p=Popen(['ls','-l'],stdout=PIPE).communicate()[0]

    代替shell管道:

    p=`dmesg | grep cpu`

    等效于

    p1=Popen(['dmesg'],stdout=PIPE)

    p2=Popen(['grep','cpu'],stdin=p1.stdout,stdout=PIPE)

    output = p2.communicate()[0]

    output

    cpu0: on acpi0\nacpi_throttle0: on cpu0\n

    >>> p1=subprocess.Popen('cat /etc/passwd',shell=True,stdout=subprocess.PIPE)

    >>> p2=subprocess.Popen('grep 0:0',shell=True,stdin=p1.stdout,stdout=subprocess.PIPE)

    >>> p3=subprocess.Popen("cut -d ':' -f 7",shell=True,stdin=p2.stdout,stdout=subprocess.PIPE)

    >>> print p3.stdout.read()

    代替os.system()

    lsl = os.system('ls '+'-l')

    这个是一个返回状态

    等效于

    p=Popen('ls -l', shell=True)

    lsl=os.waitpid(p.pid,0)[1]

    注意:

    通常并不需要用shell来调用程序。用subprocess可以更方便地得到子程序的返回值。

    其实,更真实的替换是:

    try:

    retcode = call(“mycmd” + ” myarg”, shell=True)

    if retcode < 0:

    print >>sys.stderr, “Child was terminated by signal”, -retcode

    else:

    print >>sys.stderr, “Child returned”, retcode

    except OSError, e:

    print >>sys.stderr, “Execution failed:”, e

    代替os.spawn系列

    P_NOWAIT的例子

    pid = os.spawnlp(os.P_NOWAIT, “/bin/mycmd”, “mycmd”, “myarg”)

    等效于

    pid = Popen(["/bin/mycmd", "myarg"]).pid

    P_WAIT的例子

    retcode = os.spawnlp(os.P_WAIT, “/bin/mycmd”, “mycmd”, “myarg”)

    等效于

    retcode = call(["/bin/mycmd", "myarg"])

    返回值处理:

    pipe = os.popen(“cmd”, ‘w’)

    ...

    rc = pipe.close()

    if rc != None and rc % 256:

    print “There were some errors”

    等效于

    process = Popen(“cmd”, ‘w’, shell=True, stdin=PIPE)

    ...

    process.stdin.close()

    if process.wait() != 0:

    print “There were some errors

    参考链接:https://blog.csdn.net/wintersweetzeng/article/details/47319115

    展开全文
  • 自己写的popen

    2012-11-14 18:21:54
    自己编写popen函数,可以学习学习哦,网上有popen的源代码
  • 所以在假期,我仔细的在网上找了找,看了看subprocess,发现subprocess.Popen有一个参数preexec_fn,调用subprocess.Popen时传递preexec_fn=os.setsid或者preexec_fn=os.setpgrp,然后在超时的时候执行os.killpg(p....
  • popen 阻塞

    2020-12-31 06:35:48
    sys.stdin, or objects returned by open() or os.popen()), socket objects returned by socket.socket().You may also define a wrapper class yourself, as long as it has an appropriate fileno() method ...
  • 先简单的解释一下popen函数吧~popen() 函数通过创建一个管道,调用 fork 产生一个子进程,执行一个 shell 以运行命令来开启一个进程。这个进程必须由 pclose() 函数关闭,而不是 fclose() 函数。pclose() 函数关闭...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 56,010
精华内容 22,404
关键字:

popen