python中子进程发送信号父进程怎么互发信号

Python013

python中子进程发送信号父进程怎么互发信号,第1张

ubuntu下,也就是linux下,通常会用kill -事件编号实现。 你查一下LINUX下的事件就明白了。 kill进程号 实现上是发了一个信号给指定的进程。 在python里,也可以加载事件处理模块,处理来自其它程序发过来的信号, 当然你可以用KILL工具发信号...

在了解了Linux的信号基础之 后,Python标准库中的signal包就很容易学习和理解。signal包负责在Python程序内部处理信号,典型的操作包括预设信号处理函数,暂 停并等待信号,以及定时发出SIGALRM等。要注意,signal包主要是针对UNIX平台(比如Linux, MAC OS),而Windows内核中由于对信号机制的支持不充分,所以在Windows上的Python不能发挥信号系统的功能。

信号(signal)-- 进程之间通讯的方式,是一种软件中断。一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号。

定义信号名

signal包定义了各个信号名及其对应的整数,比如:

import signal

print(signal.SIGABRT)

print(signal.SIG_DFL)

Python所用的信号名与Linux一致,可以通过$ man 7 signal 查询

预设信号处理函数

signal包的核心是使用signal.signal()函数来预设(register)信号处理函数,如下所示:

singnal.signal(signalnum, handler)

signalnum为某个信号,handler为该信号的处理函数。我们在信号基础里提到,进程可以无视信号,可以采取默认操作,还可以自定义操作。当handler为signal.SIG_IGN时,信号被无视(ignore)。当handler为singal.SIG_DFL,进程采取默认操作(default)。当handler为一个函数名时,进程采取函数中定义的操作。

import signal

# Define signal handler function

def myHandler(signum, frame):

print('I received: ', signum)

# register signal.SIGTSTP's handler

signal.signal(signal.SIGTSTP, myHandler)

signal.pause()

print('End of Signal Demo')

# 有问题待测试

在主程序中,我们首先使用signal.signal()函数来预设信号处理函数。然后我们执行signal.pause()来让该进程暂停以等待信号, 以等待信号。当信号SIGUSR1被传递给该进程时,进程从暂停中恢复,并根据预设,执行SIGTSTP的信号处理函数myHandler()。 myHandler的两个参数一个用来识别信号(signum),另一个用来获得信号发生时,进程栈的状况(stack frame)。这两个参数都是由signal.singnal()函数来传递的。

上面的程序可以保存在一个文件中(比如test.py)。我们使用如下方法运行:

$python test.py

以便让进程运行。当程序运行到signal.pause()的时候,进程暂停并等待信号。此时,通过按下CTRL+Z向该进程发送SIGTSTP信号。我们可以看到,进程执行了myHandle()函数, 随后返回主程序,继续执行。(当然,也可以用$ps查询process ID, 再使用$kill来发出信号。)

(进程并不一定要使用signal.pause()暂停以等待信号,它也可以在进行工作中接受信号,比如将上面的signal.pause()改为一个需要长时间工作的循环。)

我们可以根据自己的需要更改myHandler()中的操作,以针对不同的信号实现个性化的处理。

定时发出SIGALRM信号

一个有用的函数是signal.alarm(),它被用于在一定时间之后,向进程自身发送SIGALRM信号:

import signal

# Define signal handler function

def myHandler(signum, frame):

print("Now, it's the time")

exit()

# register signal.SIGALRM's handler

signal.signal(signal.SIGALRM, myHandler)

signal.alarm(5)

while True:

print('not yet')

我们这里用了一个无限循环以便让进程持续运行。在signal.alarm()执行5秒之后,进程将向自己发出SIGALRM信号,随后,信号处理函数myHandler开始执行。

发送信号

signal包的核心是设置信号处理函数。除了signal.alarm()向自身发送信号之外,并没有其他发送信号的功能。但在os包中,有类似于linux的kill命令的函数,分别为

os.kill(pid, sid)

os.killpg(pgid, sid)

分别向进程和进程组(见Linux进程关系)发送信号。sid为信号所对应的整数或者singal.SIG*。

实际上signal, pause,kill和alarm都是Linux应用编程中常见的C库函数,在这里,我们只不过是用Python语言来实现了一下。实际上,Python 的解释器是使用C语言来编写的,所以有此相似性也并不意外。此外,在Python 3.4中,signal包被增强,信号阻塞等功能被加入到该包中。我们暂时不深入到该包中。

总结

signal.SIG*

signal.signal()

signal.pause()

signal.alarm()

用例子说明吧,常用的不多

PyQt中的线程类 QtCore.QThread ,使用时继承QThread类

启动界面的线程暂称为UI线程。界面执行命令时都在自己的UI线程中。

如果在UI线程中执行网络连接和数据库操作等耗时的操作,界面会被卡住,Windows下有可能会出现“无响应”的警告。

阻塞UI线程会降低用户体验和应用稳定性。因此我们可以把耗时操作放在线程中去执行。

QThread代表一个线程,我们可以复写run函数来执行我们要的操作。

QThread可以使用 QtCore.pyqtSignal 来与界面交互和传输数据。

PyQt4 QThread 代码示例

•Python2.7

# -*- coding: utf-8 -*-

import sys

from PyQt4 import QtCore

from PyQt4.QtCore import QCoreApplication

from PyQt4.QtGui import QWidget, QPushButton, QApplication, QTextBrowser

class TimeThread(QtCore.QThread):

signal_time = QtCore.pyqtSignal(str, int) # 信号

def __init__(self, parent=None):

super(TimeThread, self).__init__(parent)

self.working = True

self.num = 0

def start_timer(self):

self.num = 0

self.start()

def run(self):

while self.working:

print "Working", self.thread()

self.signal_time.emit("Running time:", self.num) # 发送信号

self.num += 1

self.sleep(1)

class TimeDialog(QWidget):

def __init__(self):

super(TimeDialog, self).__init__()

self.timer_tv = QTextBrowser(self)

self.init_ui()

self.timer_t = TimeThread()

self.timer_t.signal_time.connect(self.update_timer_tv)

def init_ui(self):

self.resize(300, 200)

self.setWindowTitle('TimeDialog')

self.timer_tv.setText("Wait")

self.timer_tv.setGeometry(QtCore.QRect(10, 145, 198, 26))

self.timer_tv.move(0, 15)

btn1 = QPushButton('Quit', self)

btn1.setToolTip('Click to quit')

btn1.resize(btn1.sizeHint())

btn1.move(200, 150)

btn1.clicked.connect(QCoreApplication.instance().quit)

start_btn = QPushButton('Start', self)

start_btn.setToolTip("Click to start")

start_btn.move(50, 150)

self.connect(start_btn, QtCore.SIGNAL("clicked()"), self.click_start_btn)

def click_start_btn(self):

self.timer_t.start_timer()

def update_timer_tv(self, text, number):

self.timer_tv.setText(self.tr(text + " " + str(number)))

if __name__ == '__main__':

app = QApplication(sys.argv)

time_dialog = TimeDialog()

time_dialog.show()

sys.exit(app.exec_())

QThread中使用的信号 signal_time = QtCore.pyqtSignal(str, int) 指定了参数str和int

发送信号 self.signal_time.emit("Running time:", self.num)

外部接收信号 self.timer_t.signal_time.connect(self.update_timer_tv)

信号连接到方法 update_timer_tv(self, text, number) ,注意信号与方法的参数要一一对应

使用中我们可以定义多种不同的信号 QtCore.pyqtSignal

启动线程,调用 start()