Python线程通信
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python线程通信相关的知识,希望对你有一定的参考价值。
subprocess
作用
模块用于生产新的进程,连接到其输入、输出、错误管道,并获取其返回值
1. 如何使用subprocess模块
启动子进程的推荐方法是使用以下方便功能。 对于更高级的用例,当这些不满足您的需要时,使用底层的Popen interface
subprocess.
call
(args, *, stdin=None, stdout=None, stderr=None, shell=False)
作用:调用如args所示的系统命令,等待命令完成,返回returncode
Example:
>>> subprocess.call(["ls", "-l"]) 0 >>> subprocess.call("exit 1", shell=True) 1
警告:使用shell = True可能是一个安全隐患。
注意:不要使用stdout = PIPE或stderr = PIPE,因为它可能发生子进程输出的死锁。 当需要管道时,使用popen与communicate()方法
subprocess.
check_call
(args, *, stdin=None, stdout=None, stderr=None, shell=False)
运行带参数的命令。 等待命令完成。 如果返回码为零,那么返回,否则抛出CalledProcessError。 CalledProcessError对象将在returncode属性中具有返回码
Example:
>>> subprocess.check_call(["ls", "-l"]) 0 >>> subprocess.check_call("exit 1", shell=True) Traceback (most recent call last): ... subprocess.CalledProcessError: Command ‘exit 1‘ returned non-zero exit status 1
subprocess.
check_output
(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
运行系统命令,并将输出返回给一个字节字符串,如果返回值不为0,则抛出CalledProcessError异常。
Example:
>>> subprocess.check_output(["echo", "Hello World!"]) ‘Hello World!\n‘ >>> subprocess.check_output("exit 1", shell=True) Traceback (most recent call last): ... subprocess.CalledProcessError: Command ‘exit 1‘ returned non-zero exit status 1
想要捕获错误信息,使用stderr=subprocess.STDOUT:
>>> subprocess.check_output( ... "ls non_existent_file; exit 0", ... stderr=subprocess.STDOUT, ... shell=True) ‘ls: non_existent_file: No such file or directory\n‘
- subprocess.PIPE
特殊值,可以用作popen的stdin,stdout或stderr参数,并指示应打开标准流的管道。
subprocess.
STDOUT
可以用作Popen的stderr参数的特殊值,表示标准错误应该作为标准输出进入相同的句柄。
-
为了支持各种各样的用例,Popen构造函数(和方便函数)接受大量的可选参数。对于大多数典型的用例,许多这些参数可以安全地保留其默认值。最常需要的参数是:
args是所有调用所必需的,应该是一个字符串或一系列程序参数。提供参数序列通常是优选的,因为它允许模块处理任何所需的转义和引用参数(例如,以允许文件名中的空格)。如果传递单个字符串,则shell必须为True(见下文),否则字符串必须简单地命名要执行的程序,而不指定任何参数。
stdin,stdout和stderr分别指定执行程序的标准输入,标准输出和标准错误文件句柄。有效值为PIPE,现有文件描述符(正整数),现有文件对象和无。 PIPE表示应该创建一个新的管道给孩子。使用默认设置None,不会发生重定向;子进程的文件句柄将从父进程继承。此外,stderr可以是STDOUT,它指示来自子进程的stderr数据应该捕获到与stdout相同的文件句柄中。
当stdout或stderr是管道,universal_newlines为True时,所有行尾都将转换为‘\ n‘,如open()的通用换行符‘U‘模式参数所述。
如果shell为True,指定的命令将通过shell执行。如果你使用Python主要用于增强的控制流,它提供了大多数系统shell,并仍然想要方便地访问其他shell功能,如shell管道,文件名通配符,环境变量扩展和扩展?到用户的家
使用了shell=True这个参数。这个时候,我们使用一整个字符串,而不是一个表来运行子进程。Python将先运行一个shell,再用这个shell来解释这整个字符串。
Example:
import subprocess out = subprocess.call("ls -l", shell=True) out = subprocess.call("cd ..", shell=True)
- Popen 构造器
-
此模块中的基础过程创建和管理由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)
在新进程中执行子程序。在Unix上,类使用os.execvp() - 类行为来执行子程序。在Windows上,类使用Windows CreateProcess()函数。 Popen的参数如下。args应该是一个程序参数序列或者一个单个字符串。默认情况下,如果args是一个序列,则要执行的程序是args中的第一个项目。如果args是字符串,解释是平台相关的,如下所述。有关与默认行为的其他差异,请参阅shell和可执行参数。除非另有说明,建议将args作为序列传递。
- Example:
-
>>> import shlex, subprocess >>> command_line = raw_input() /bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo ‘$MONEY‘" >>> args = shlex.split(command_line) >>> print args [‘/bin/vikings‘, ‘-input‘, ‘eggs.txt‘, ‘-output‘, ‘spam spam.txt‘, ‘-cmd‘, "echo ‘$MONEY‘"] >>> p = subprocess.Popen(args) # Success!
-
shell参数(默认为False)指定是否使用shell作为程序执行。 如果shell为True,则建议将args作为字符串而不是序列传递。
在Unix上,shell = True,shell默认为/ bin / sh。 如果args是字符串,则该字符串指定要通过shell执行的命令。 这意味着字符串的格式必须与在shell提示符下键入时的格式完全一致。 这包括,例如,引用或反斜杠转义文件名中带有空格。 如果args是序列,则第一个项指定命令字符串,任何其他项将被视为shell本身的附加参数。 也就是说,Popen相当于:
-
Popen([‘/bin/sh‘, ‘-c‘, args[0], args[1], ...])
- 在shell = true的Windows上,COMSPEC环境变量指定默认shell。 只有当你需要在Windows上指定shell = True的时候,你希望执行的命令是内置在shell中(例如dir或copy)。 您不需要shell = True来运行批处理文件或基于控制台的可执行文件。
- bufsize(如果给定)与内置open()函数的相应参数意义相同:0表示无缓冲,1表示行缓冲,任何其他正值表示使用大小为(大约)的缓冲区。 负bufsize意味着使用系统默认值,这通常意味着完全缓冲。 bufsize的默认值为0(未缓冲)。
- 如果遇到性能问题,尝试通过将bufsize设置为-1或足够大的正值(例如4096)来启用缓冲。
-
如果preexec_fn设置为可调用对象,则该对象将在子进程中在子进程执行之前被调用。 (仅限Unix)
如果close_fds为true,除了0,1和2之外的所有文件描述符将在子进程执行之前关闭。 (仅限Unix)。 或者,在Windows上,如果close_fds为true,则子进程将不继承任何句柄。 请注意,在Windows上,您不能将close_fds设置为true,也可以通过设置stdin,stdout或stderr重定向标准句柄。
如果cwd不是None,子进程的当前目录在执行之前将被更改为cwd。 注意,在搜索可执行文件时不考虑此目录,因此您不能指定程序相对于cwd的路径。
如果env不是None,它必须是定义新进程的环境变量的映射; 这些是使用而不是继承当前进程的环境,这是默认行为。
-
注意如果指定,env必须提供程序执行所需的任何变量。 在Windows上,为了运行side-by-side程序集,指定的env必须包含一个有效的SystemRoot。
如果universal_newlines为True,文件对象stdout和stderr在通用换行模式下作为文本文件打开。 行可以由‘\ n‘,Unix行尾约定,‘\ r‘,旧的Macintosh约定或‘\ r \ n‘(Windows约定)中的任何一个终止。 所有这些外部表示被Python程序看作‘\ n‘。 - Exception
-
如果在新程序开始执行之前,在子进程中引发的异常,将在父进程中重新生成。 此外,异常对象将有一个额外的属性称为child_traceback,这是一个字符串,包含从孩子的角度的追溯信息。
最常见的异常是OSError。 例如,当尝试执行不存在的文件时,会发生这种情况。 应用程序应准备OSError异常。
如果使用无效参数调用Popen,将引发ValueError。
如果被调用的进程返回非零返回码,check_call()和check_output()将引发CalledProcessError。
-
- Security
- 与其他popen函数不同,这个实现不会隐式地调用系统shell。 这意味着所有字符,包括shell元字符,都可以安全地传递给子进程。 显然,如果shell被显式地调用,则应用程序有责任确保所有空格和元字符被适当地引用。
Popen对象
-
import subprocess child = subprocess.Popen(["ping","-c","5","www.google.com"]) child.wait() print("parent process")
此外,你还可以在父进程中对子进程进行其它操作,比如我们上面例子中的child对象:
child.poll() # 检查子进程状态
child.kill() # 终止子进程
child.send_signal() # 向子进程发送信号
child.terminate() # 终止子进程
Popen.
poll
()
Popen.
wait
()
- Popen.communicate(input = None)
与进程交互:将数据发送到stdin。 从stdout和stderr读取数据,直到达到文件结束。 等待进程终止。 可选输入参数应为要发送到子进程的字符串,如果没有数据应发送到子进程,则为None。
communicate()返回一个元组(stdoutdata,stderrdata)。
注意,如果你想发送数据到进程的stdin,你需要使用stdin = PIPE来创建Popen对象。 类似地,要在结果元组中获取除了None之外的任何值,您需要同时给予stdout = PIPE和/或stderr = PIPE。
Popen.stdin
如果stdin参数是PIPE,则此属性是向子进程提供输入的文件对象。 否则,它为无。
Popen.stdout
如果stdout参数是PIPE,则此属性是提供子进程输出的文件对象。 否则,它为无。
Popen.stderr
如果stderr参数是PIPE,则此属性是一个文件对象,它提供子进程的错误输出。 否则,它为无。
Popen.pid
子进程的进程ID。
请注意,如果将shell参数设置为True,那么这是生成的shell的进程ID。
Popen.returncode
子返回码,由poll()和wait()设置(间接通过communic())。 无值表示进程尚未终止。
负值-N表示子节点由信号N(仅限Unix)终止。
以上是关于Python线程通信的主要内容,如果未能解决你的问题,请参考以下文章
Motan在服务provider端用于处理request的线程池