signal
---为异步事件设置处理程序¶
这个模块提供了在Python中使用信号处理程序的机制。
一般规则¶
这个 signal.signal()
函数允许在接收到信号时定义要执行的自定义处理程序。安装了少量默认处理程序: SIGPIPE
被忽略(因此管道和套接字上的写入错误可以报告为普通的python异常)和 SIGINT
被翻译成 KeyboardInterrupt
如果父进程没有更改,则出现异常。
特定信号的处理程序一旦设置,将一直保持安装状态,直到显式重置为止(无论底层实现如何,python都模拟BSD样式的接口),但 SIGCHLD
在底层实现之后。
执行python信号处理程序¶
Python信号处理程序不会在低级(C)信号处理程序内执行。相反,低级信号处理程序设置一个标志,它告诉 virtual machine 稍后执行相应的python信号处理程序(例如在下一个 bytecode 指令)。这会产生以下后果:
捕捉同步错误是没有意义的,比如
SIGFPE
或SIGSEGV
这是由C代码中的无效操作引起的。python将从信号处理程序返回到C代码,这可能再次引发相同的信号,导致python明显挂起。从python 3.3开始,您可以使用faulthandler
报告同步错误的模块。纯C语言实现的长时间运行的计算(例如,在大文本体上匹配正则表达式)可以在任意时间内不间断运行,而不管接收到任何信号。计算完成后将调用python信号处理程序。
信号和线程¶
Python信号处理程序总是在主解释器的主Python线程中执行,即使信号是在另一个线程中接收到的。这意味着信号不能用作线程间通信的手段。您可以使用 threading
模块代替。
此外,只允许主解释器的主线程设置新的信号处理程序。
模块内容¶
在 3.5 版更改: 信号(sig*),处理程序 (SIG_DFL
, SIG_IGN
和Sig面具 (SIG_BLOCK
, SIG_UNBLOCK
, SIG_SETMASK
)下面列出的相关常数被转换为 enums
. getsignal()
, pthread_sigmask()
, sigpending()
和 sigwait()
函数返回人可读的 enums
.
中定义的变量 signal
模块包括:
- signal.SIG_IGN¶
这是另一个标准的信号处理程序,它只会忽略给定的信号。
- signal.SIGALRM¶
计时器信号来自 alarm(2) .
Availability UNIX。
- signal.SIGBREAK¶
从键盘中断(CTRL+BREAK)。
Availability :Windows。
- signal.SIGBUS¶
总线错误(内存访问错误)。
Availability UNIX。
- signal.SIGCHLD¶
子进程已停止或终止。
Availability UNIX。
- signal.SIGCONT¶
如果进程当前已停止,请继续该进程
Availability UNIX。
- signal.SIGFPE¶
浮点异常。例如,除以零。
参见
ZeroDivisionError
当除法或模运算的第二个参数为零时引发。
- signal.SIGHUP¶
在控制终端检测到挂断或控制过程死亡。
Availability UNIX。
- signal.SIGILL¶
非法指令。
- signal.SIGINT¶
从键盘中断(CTRL+C)。
默认操作是
KeyboardInterrupt
.
- signal.SIGKILL¶
杀戮信号。
它不能被捕获、阻止或忽略。
Availability UNIX。
- signal.SIGPIPE¶
断管:在没有读卡器的情况下写入管道。
默认操作是忽略信号。
Availability UNIX。
- signal.SIGSEGV¶
分段错误:无效的内存引用。
- signal.SIGTERM¶
终止信号。
- signal.SIGUSR1¶
用户定义信号1。
Availability UNIX。
- signal.SIGUSR2¶
用户定义信号2。
Availability UNIX。
- signal.SIGWINCH¶
窗口大小调整信号。
Availability UNIX。
- SIG*
所有的信号数字都是用符号来定义的。例如,挂断信号定义为
signal.SIGHUP
;变量名与C程序中使用的名称相同,如<signal.h>
. “:c:func:signal”的Unix手册页列出了现有的信号(在某些系统上,这是 signal(2) ,在其他列表中 signal(7) )请注意,并非所有系统都定义相同的信号名称集;只有系统定义的那些名称才由该模块定义。
- signal.CTRL_C_EVENT¶
对应于 Ctrl+C 击键事件。此信号只能用于
os.kill()
.Availability :Windows。
3.2 新版功能.
- signal.CTRL_BREAK_EVENT¶
对应于 Ctrl+Break 击键事件。此信号只能用于
os.kill()
.Availability :Windows。
3.2 新版功能.
- signal.NSIG¶
比最高信号号多一个。
- signal.ITIMER_VIRTUAL¶
仅当进程正在执行时减少间隔计时器,并在到期时传递sigvtalrm。
- signal.ITIMER_PROF¶
当进程执行时和系统代表进程执行时,递减间隔计时器。再加上ITimer_virtual,该计时器通常用于分析应用程序在用户和内核空间中花费的时间。SigProf在到期时交付。
- signal.SIG_BLOCK¶
的可能值 how 参数到
pthread_sigmask()
表示信号被阻塞。3.3 新版功能.
- signal.SIG_UNBLOCK¶
的可能值 how 参数到
pthread_sigmask()
表示信号将被解除阻塞。3.3 新版功能.
- signal.SIG_SETMASK¶
的可能值 how 参数到
pthread_sigmask()
表示要更换信号屏蔽。3.3 新版功能.
这个 signal
模块定义了一个异常:
- exception signal.ItimerError¶
引发以指示来自基础的错误
setitimer()
或getitimer()
实施。如果将无效的间隔计时器或负时间传递给setitimer()
. 此错误是的子类型OSError
.
这个 signal
模块定义以下功能:
- signal.alarm(time)¶
如果 time 为非零,此函数要求
SIGALRM
信号发送到进程 time 秒。任何先前计划的警报都将被取消(任何时候只能计划一个警报)。返回的值是任何先前设置的警报发出前的秒数。如果 time 为零,不计划任何警报,并且取消任何计划的警报。如果返回值为零,则当前不计划报警。Availability :Unix系统。参见手册页 alarm(2) 更多信息。
- signal.getsignal(signalnum)¶
返回信号的当前信号处理程序 信号符号 . 返回的值可以是可调用的python对象,也可以是特殊值之一
signal.SIG_IGN
,signal.SIG_DFL
或None
. 在这里,signal.SIG_IGN
意味着信号之前被忽略了,signal.SIG_DFL
意味着处理信号的默认方式以前是在使用中的,并且None
意味着之前的信号处理程序不是从python安装的。
- signal.valid_signals()¶
返回此平台上的一组有效信号号。这可能小于
range(1, NSIG)
如果系统保留一些信号供内部使用。3.8 新版功能.
- signal.pause()¶
使进程休眠,直到接收到信号;然后将调用相应的处理程序。不返回任何内容。
Availability :Unix系统。参见手册页 signal(2) 更多信息。
也见
sigwait()
,sigwaitinfo()
,sigtimedwait()
和sigpending()
.
- signal.raise_signal(signum)¶
向调用进程发送信号。什么也不返回。
3.8 新版功能.
- signal.pidfd_send_signal(pidfd, sig, siginfo=None, flags=0)¶
发送信号 sig 到由文件描述符引用的进程 pidfd公司 . Python当前不支持 siginfo公司 参数;必须是
None
. 这个 旗帜 参数是为将来的扩展提供的;当前未定义标志值。见 pidfd_send_signal(2) 详细信息请参见手册页。
Availability :Linux 5.1版+
3.9 新版功能.
- signal.pthread_kill(thread_id, signalnum)¶
发送信号 信号符号 线程 thread_id ,与调用方处于同一进程中的另一个线程。目标线程可以执行任何代码(python或not)。但是,如果目标线程正在执行python解释器,则python信号处理程序将 executed by the main thread of the main interpreter . 因此,向特定的python线程发送信号的唯一目的是强制正在运行的系统调用失败
InterruptedError
.使用
threading.get_ident()
或ident
属性threading.Thread
要为其获取适当值的对象 thread_id .如果 信号符号 为0,则不发送信号,但仍执行错误检查;这可用于检查目标线程是否仍在运行。
提出一个 auditing event
signal.pthread_kill
带着论据thread_id
,signalnum
.Availability :Unix系统。参见手册页 pthread_kill(3) 更多信息。
也见
os.kill()
.3.3 新版功能.
- signal.pthread_sigmask(how, mask)¶
获取和/或更改调用线程的信号屏蔽。信号屏蔽是当前为呼叫者阻止传递的一组信号。将旧的信号屏蔽作为一组信号返回。
调用的行为取决于 how ,如下所述。
SIG_BLOCK
:阻塞信号集是当前集和 mask 参数。SIG_UNBLOCK
:中的信号 mask 从当前的一组阻塞信号中删除。允许尝试解锁未被阻塞的信号。SIG_SETMASK
:阻塞信号集设置为 mask 参数。
mask is a set of signal numbers (e.g. {
signal.SIGINT
,signal.SIGTERM
}). Usevalid_signals()
for a full mask including all signals.例如,
signal.pthread_sigmask(signal.SIG_BLOCK, [])
读取调用线程的信号屏蔽。SIGKILL
和SIGSTOP
无法阻止。Availability :Unix系统。参见手册页 sigprocmask(2) 和 pthread_sigmask(3) 更多信息。
也见
pause()
,sigpending()
和sigwait()
.3.3 新版功能.
- signal.setitimer(which, seconds, interval=0.0)¶
设置给定的间隔计时器(其中一个
signal.ITIMER_REAL
,signal.ITIMER_VIRTUAL
或signal.ITIMER_PROF
)由 哪一个 在…之后开火 秒 (接受浮动,不同于alarm()
)之后每 间隔 秒(如果) 间隔 是非零)。由指定的间隔计时器 哪一个 可通过设置清除 秒 到零。当间隔计时器触发时,会向进程发送一个信号。发送的信号取决于使用的计时器;
signal.ITIMER_REAL
将交付SIGALRM
,signal.ITIMER_VIRTUAL
发送SIGVTALRM
和signal.ITIMER_PROF
将交付SIGPROF
.旧值作为元组返回:(delay,interval)。
试图传递无效的间隔计时器将导致
ItimerError
.Availability UNIX。
- signal.getitimer(which)¶
返回由指定的给定间隔计时器的当前值 哪一个 .
Availability UNIX。
- signal.set_wakeup_fd(fd, *, warn_on_full_buffer=True)¶
将唤醒文件描述符设置为 fd . 当接收到信号时,信号号作为一个单字节写入fd。库可以使用它来唤醒轮询或选择调用,从而使信号得到完全处理。
返回旧的wakeup fd(如果未启用文件描述符wakeup,则返回-1)。如果 fd 是-1,文件描述符唤醒被禁用。如果不是- 1, fd 必须是非阻塞的。由库决定从中删除任何字节 fd 在调用poll或再次选择之前。
启用线程时,此函数只能从 the main thread of the main interpreter ;尝试从其他线程调用它将导致
ValueError
将引发异常。使用此函数有两种常见方法。在这两种方法中,当信号到达时,使用fd来唤醒,但是它们在确定方法上有所不同 哪一个 信号已到达。
在第一种方法中,我们从fd的缓冲区中读取数据,字节值给出信号号。这很简单,但在极少数情况下会遇到一个问题:一般情况下,fd会有有限的缓冲空间,如果太多的信号到达得太快,那么缓冲空间可能会变满,一些信号可能会丢失。如果使用此方法,则应设置
warn_on_full_buffer=True
当信号丢失时,至少会导致将警告打印到stderr。在第二种方法中,我们使用唤醒fd only 对于唤醒,忽略实际字节值。在这种情况下,我们只关心fd的缓冲区是空的还是非空的;一个完整的缓冲区根本不表示有问题。如果使用此方法,则应设置
warn_on_full_buffer=False
,这样您的用户就不会被虚假的警告消息所混淆。在 3.5 版更改: 在Windows上,该函数现在还支持套接字句柄。
在 3.7 版更改: 补充
warn_on_full_buffer
参数。
- signal.siginterrupt(signalnum, flag)¶
更改系统调用重新启动行为:如果 flag 是
False
,系统调用将在被信号中断时重新启动。 信号符号 ,否则系统调用将中断。什么也不返回。Availability :Unix系统。参见手册页 siginterrupt(3) 更多信息。
请注意,安装信号处理程序时
signal()
将通过隐式调用将重新启动行为重置为可中断siginterrupt()
以真 flag 给定信号的值。
- signal.signal(signalnum, handler)¶
设置信号处理程序 信号符号 对函数 处理程序 . 处理程序 可以是具有两个参数(见下文)或一个特殊值的可调用python对象
signal.SIG_IGN
或signal.SIG_DFL
. 将返回上一个信号处理程序(请参见getsignal()
以上)。(参见Unix手册页 signal(2) 更多信息。)启用线程时,此函数只能从 the main thread of the main interpreter ;尝试从其他线程调用它将导致
ValueError
将引发异常。这个 处理程序 用两个参数调用:信号号和当前堆栈帧 (
None
或框架对象;有关框架对象的描述,请参见 description in the type hierarchy 或查看中的属性描述inspect
模块)。在Windows上,
signal()
只能用调用SIGABRT
,SIGFPE
,SIGILL
,SIGINT
,SIGSEGV
,SIGTERM
或SIGBREAK
. 一ValueError
在任何其他情况下都会被引发。注意,并非所有系统都定义相同的一组信号名称;一个AttributeError
如果信号名称未定义为SIG*
模块级常数。
- signal.sigpending()¶
检查等待传递到调用线程的一组信号(即,阻塞时发出的信号)。返回一组挂起的信号。
Availability :Unix系统。参见手册页 sigpending(2) 更多信息。
也见
pause()
,pthread_sigmask()
和sigwait()
.3.3 新版功能.
- signal.sigwait(sigset)¶
暂停调用线程的执行,直到传递信号集中指定的一个信号为止 西格特 . 函数接受信号(将其从挂起的信号列表中删除),并返回信号号。
Availability :Unix系统。参见手册页 sigwait(3) 更多信息。
也见
pause()
,pthread_sigmask()
,sigpending()
,sigwaitinfo()
和sigtimedwait()
.3.3 新版功能.
- signal.sigwaitinfo(sigset)¶
暂停调用线程的执行,直到传递信号集中指定的一个信号为止 西格特 . 函数接受信号并将其从挂起的信号列表中删除。如果其中一个信号 西格特 已经为调用线程挂起,函数将立即返回有关该信号的信息。对于传递的信号,不调用信号处理程序。函数引发
InterruptedError
如果被不在 西格特 .返回值是表示包含在
siginfo_t
结构,即:si_signo
,si_code
,si_errno
,si_pid
,si_uid
,si_status
,si_band
.Availability :Unix系统。参见手册页 sigwaitinfo(2) 更多信息。
也见
pause()
,sigwait()
和sigtimedwait()
.3.3 新版功能.
在 3.5 版更改: 如果被不在中的信号中断,则现在重试该函数。 西格特 信号处理程序不会引发异常(请参见 PEP 475 理由)。
- signal.sigtimedwait(sigset, timeout)¶
类似于
sigwaitinfo()
,但需要额外的 timeout 指定超时的参数。如果 timeout 指定为0
,执行轮询。返回None
如果发生超时。Availability :Unix系统。参见手册页 sigtimedwait(2) 更多信息。
也见
pause()
,sigwait()
和sigwaitinfo()
.3.3 新版功能.
在 3.5 版更改: 函数现在重新计算 timeout 如果被不在的信号中断 西格特 信号处理程序不会引发异常(请参见 PEP 475 理由)。
例子¶
下面是一个最小的示例程序。它使用 alarm()
用于限制等待打开文件所花费的时间的函数;如果该文件用于可能无法打开的串行设备,则此函数非常有用,这通常会导致 os.open()
无限期地悬挂。解决方法是在打开文件之前设置5秒警报;如果操作时间过长,将发送警报信号,处理程序将引发异常。::
import signal, os
def handler(signum, frame):
print('Signal handler called with signal', signum)
raise OSError("Couldn't open device!")
# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)
# This open() may hang indefinitely
fd = os.open('/dev/ttyS0', os.O_RDWR)
signal.alarm(0) # Disable the alarm
关于SIGPIN的注释¶
将程序的输出管道连接到工具,如 head(1) 将导致 SIGPIPE
当标准输出的接收器提前关闭时发送给您的进程的信号。这会导致一个异常,比如 BrokenPipeError: [Errno 32] Broken pipe
. 要处理此情况,请将入口点封装为捕获此异常,如下所示:
import os
import sys
def main():
try:
# simulate large output (your code replaces this loop)
for x in range(10000):
print("y")
# flush output here to force SIGPIPE to be triggered
# while inside this try block.
sys.stdout.flush()
except BrokenPipeError:
# Python flushes standard streams on exit; redirect remaining output
# to devnull to avoid another BrokenPipeError at shutdown
devnull = os.open(os.devnull, os.O_WRONLY)
os.dup2(devnull, sys.stdout.fileno())
sys.exit(1) # Python exits with error code 1 on EPIPE
if __name__ == '__main__':
main()
不设置 SIGPIPE
对…的处置 SIG_DFL
为了避免 BrokenPipeError
.这样做会导致程序意外退出,也会在程序仍在写入时中断任何套接字连接。