您的位置:首页 > 编程语言 > Python开发

Python process

2016-04-03 22:15 393 查看


进程通信


subprocess

执行程序,获取返回码或输出信息。

call: 返回 ExitCode。
check_call: 如果 ExitCode = 0,抛出 CalledProcessError 异常。
check_output: 返回输出信息。ExitCode = 0 抛出异常。

命令行参数可以用 shlex.split 分解成列表。
>>> from subprocess import *
>>> from shlex import split

>>> s = check_output(split("ls -l"))
>>> print s
total 0
drwx------+ 4 yuhen staff 136 1 11 07:40 Desktop
drwx------+ 10 yuhen staff 340 1 4 01:53 Documents
drwx------+ 4 yuhen staff 136 1 11 08:35 Downloads
drwx------@ 56 yuhen staff 1904 1 11 08:28 Library
drwx------+ 3 yuhen staff 102 9 22 15:20 Movies
drwx------+ 5 yuhen staff 170 1 9 19:37 Music
drwx------+ 5 yuhen staff 170 1 3 21:14 Pictures
drwxr-xr-x+ 4 yuhen staff 136 9 15 16:21 Public


如果需要获取 ExitCode,又不想看到输出信息。可以将 stdout 重定位到 /dev/null。
>>> null = open(os.devnull, "w")
>>> call(split("ls -l"), stdout = null, stderr = null)
0


官方建议用 subprocess 代替 os.system、os.spawn、os.popen、popen2.、commands.这个传统用法。基于以后向 Python 3 迁移的需要,还是放弃所有打上 obsolete 标记的库。
>>> from subprocess import Popen, PIPE

>>> Popen('find . -name "*.py" | xargs ls -l', shell=True).wait()
-rwxr-xr-x 1 yuhen staff 286 5 29 19:24 ./main.py
-rw-r--r-- 1 yuhen staff 76 6 7 17:49 ./test.py


可以用 PIPE 改变输入输出对象。
>>> p = Popen('find . -name "*.py" | xargs ls -l', shell=True, stdout=PIPE)
>>> p.pid
71474

>>> print p.stdout.read()
-rwxr-xr-x 1 yuhen staff 286 5 29 19:24 ./main.py
-rw-r--r-- 1 yuhen staff 76 6 7 17:49 ./test.py

>>> p.wait()
0


除使用简便函数外,还可以创建 Popen 对象以获取更细节的控制。subprocess 不能控制终端和 TTY 交互程序,建议使用第三方库 Fabric 或 pexpect。进程信息可以用 psutil 获取。


22.2 signal

信号是软中断,提供了一种异步事件通知机制。Python 默认已经安装了一些信号处理器,比如 SIGPIPE 被忽略,SIGINT 引发 KeyboardInterrupt 异常,捕获 SIGTERM 调用退出函数。

常用信号

SIGINT: 用户中断 (ctrl + c)。
SIGTERM: 由 kill() 发送,进程终止。
SIGCHLD: 子进程终止。
SIGHUP: 终端会话终止。
SIGSTP: 进程暂停 (ctrl + z)。
SIGALRM: 告警。

注意: 信号 SIGKILL、SIGSTOP 不能被捕获。

signal

仅能在主线程调用 signal() 注册信号处理器函数,它会移除当前处理动作。可用 getsignal() 获取,在需要时重新注册。有两个特殊的处理器:SIG_IGN 忽略信号,SIG_DFL 默认处理。

试着用 SIGINT 代替 KeyboardInterrupt 异常来处理用户中断。
from signal import *
from time import time, sleep

def sig_handler(signum, frame):
print "exit"
exit(0)

def main():
signal(SIGINT, sig_handler)
while True:
sleep(1)
print time()

if __name__ == "__main__":
main()


输出:
$ ./main.py
1357987332.33
1357987333.33
1357987334.33
^Cexit


中断信号被拦截,我们可以自主决定是否终止进程。在 GDB 里,用 SIGINT 来处理调试中断。也有一些软件用 SIGUSR1、SIGUSR2 作为外部通知事件,比如重启什么的。信号处理会被带入 fork()创建的子进程。

pause

函数 pause() 会使进程休眠,直到进程接收到信号。信号要么被处理,要么终止进程。
def sig_handler(signum, frame):
print "sig:", signum

def main():
signal(SIGUSR1, sig_handler)

while True:
print time()
pause()


如果收到 SIGUSR1 信号,则进程苏醒后显示时间,然后再次休眠。如是其他信号,进程终止。

alarm

在 n 秒后发送一个 SIGALRM 告警信号。或用 0 秒取消所有尚未到期的告警。
signal(SIGALRM, sig_alarm) # 捕获信号
alarm(2)    # 2 秒后发送告警信号。仅一次。


timer

用来设置在 seconds 秒后发出信号,并在此以后每隔 interval 秒重复发出信号。参数 which 决定了发出何种信号。

ITIMER_REAL: SIGALRM
ITIMER_VIRTUAL: SIGVTALRM
ITIMER_PROF: SIGPROF

signal(SIGALRM, sig_alarm)
setitimer(ITIMER_REAL, 2, 5) # 2 秒后首次发出信号,随后每隔 5 秒发一次。


将 seconds 设置为 0,将清除定时器。

多进程( multi-process)

[python] view
plain copy

print?

import multiprocessing

def thread_func():

print "thread in"

while True:

pass

if __name__ == "__main__":

t1 = multiprocessing.Process(target = thread_func)

t1.start()

t2 = multiprocessing.Process(target = thread_func)

t2.start()

t1.join()

t2.join()

多线程(multi-thread)

[python] view
plain copy

print?

from threading import Thread

def thread_func():

print "thread in"

while True:

pass

if __name__ == "__main__":

t1 = Thread(target = thread_func)

t1.start()

t2 = Thread(target = thread_func)

t2.start()

t1.join()

t2.join()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: