2010-03-31 32 views
34

Có cách nào để ánh xạ một số tín hiệu (ví dụ: signal.SIGINT) với tên tương ứng của nó (ví dụ: "SIGINT") không?Nhận tên tín hiệu từ các số trong Python

Tôi muốn để có thể in tên của một tín hiệu trong nhật ký khi tôi nhận được nó, tuy nhiên tôi không thể tìm thấy một bản đồ từ số tín hiệu để tên bằng Python, ví dụ:

import signal 
def signal_handler(signum, frame): 
    logging.debug("Received signal (%s)" % sig_names[signum]) 

signal.signal(signal.SIGINT, signal_handler) 

Đối một số sig_names từ điển, vì vậy khi quá trình nhận SIGINT nó in:

Received signal (SIGINT) 

Trả lời

27

có là không có, nhưng nếu bạn không nhớ một chút hack, bạn có thể tạo ra nó như thế này:

import signal 
dict((k, v) for v, k in reversed(sorted(signal.__dict__.items())) 
    if v.startswith('SIG') and not v.startswith('SIG_')) 
+0

Nói đúng ra này sẽ lập bản đồ 1 cho 'SIG_IGN' và 'SIGHUP' trên hầu hết các nền tảng, vì vậy tôi cho rằng bài kiểm tra nên nếu' v.startswith ('SIG') và không v.startswith ('SIG _') '. –

+0

Nó cũng đôi bản đồ 6 đến 'SIGABRT' và' SIGIOT' trên Mac OS X (mặc dù chúng có thể được sử dụng thay thế cho nhau, tôi giả sử, không giống 'SIG_IGN' - không phải là tín hiệu). –

+0

@Brian: rất đúng ... nó không phải là một giải pháp hoàn hảo cho đến nay. Nhưng nó hơi độc lập với nền tảng. – Wolph

0

Vâng, help(signal) nói ở phía dưới:

DATA 
    NSIG = 23 
    SIGABRT = 22 
    SIGBREAK = 21 
    SIGFPE = 8 
    SIGILL = 4 
    SIGINT = 2 
    SIGSEGV = 11 
    SIGTERM = 15 
    SIG_DFL = 0 
    SIG_IGN = 1 

Vì vậy, điều này sẽ làm việc:

sig_names = {23:"NSIG", 22:"SIGABRT", 21:"SIGBREAK", 8:"SIGFPE", 4:"SIGILL", 
      2:"SIGINT", 11:"SIGSEGV", 15:"SIGTERM", 0:"SIG_DFL", 1:"SIG_IGN"} 
+3

Thật không may các nền tảng khác nhau có các số tín hiệu khác nhau, vì vậy đây không phải là di động. Cảm ơn, mặc dù. –

+1

Ví dụ, đây là Mac OS X 'giúp đỡ (tín hiệu) ': SIGABRT = 6 SIGALRM = 14 SIGBUS = 10 SIGCHLD = 20 SIGCONT = 19 SIGEMT = 7 SIGFPE = 8 SIGHUP = 1 SIGILL = 4 SIGINFO = 29 SIGINT = 2 SIGIO = 23 SIGIOT = 6 SIGKILL = 9 SIGPIPE = 13 SIGPROF = 27 SIGQUIT = 3 SIGSEGV = 11 SIGSTOP = 17 SIGSYS = 12 SIGTERM = 15 012.351.SIGTRAP = 5 SIGTSTP = 18 SIGTTIN = 21 SIGTTOU = 22 SIGURG = 16 SIGUSR1 = 30 SIGUSR2 = 31 SIGVTALRM = 26 SIGWINCH = 28 SIGXCPU = 24 SIGXFSZ = 25 –

+1

Ah - Tôi thực sự không nên đã nhận ra rằng, tất cả mọi thứ được xem xét, đặc biệt là kể từ khi tôi đã trải qua bao nhiêu tín hiệu khác nhau trên Windows và Linux. Giải pháp của WoLpH là sạch hơn anyway :) –

2

tôi tìm thấy bài viết này khi tôi ở trong tình trạng tương tự và đã tìm xử lý chỉ được xử lý một tín hiệu tại một thời điểm, vì vậy tôi thậm chí không cần cả một từ điển, chỉ cần tên của một tín hiệu:

sig_name = tuple((v) for v, k in signal.__dict__.iteritems() if k == signum)[0] 

có lẽ có thể một ký hiệu không cần tuple (...) [0] bit, nhưng tôi không thể hình dung ra được.

+0

signame = [v cho v, k trong tín hiệu .__ dict __. Iteritems() nếu k == signum] [0] hoạt động tốt. – dwelch91

+2

"signame = next (v cho v, k trong tín hiệu .__ dict __. Iteritems() nếu k == signum)" dừng lại khi nó tìm thấy nó thay vì tiếp tục thông qua phần còn lại của dict (cũng có, nó không có [ 0] @ssc không thích: D). – CryingCyclops

+0

Nếu v, k có nghĩa vụ phải đứng cho các khóa và giá trị, thì tên sẽ được đảo ngược, ví dụ: sig_name = tuple ((k) cho k, v trong tín hiệu .__ dict __. Iteritems() nếu v == signum) [0] Nhưng sau đó có các giá trị khác trong dict của tín hiệu có giá trị có thể khớp với v, trong trường hợp đó , tùy thuộc vào thứ tự iteritems() trả về các mục, bạn có thể in một tên vô nghĩa. – tbc0

12

Các thư viện chuẩn Python By Ví dụ cho thấy chức năng này trong các chương về tín hiệu:

SIGNALS_TO_NAMES_DICT = dict((getattr(signal, n), n) \ 
    for n in dir(signal) if n.startswith('SIG') and '_' not in n) 

Sau đó, bạn có thể sử dụng nó như thế này:

print "Terminated by signal %s" % SIGNALS_TO_NAMES_DICT[signal_number] 
+2

hoặc (có lẽ thích hợp hơn một chút) 'SIGNALS_TO_NAMES_DICT.get (signal_number," Tín hiệu chưa đặt tên:% d "% signal_number)' –

+0

Đây là câu trả lời hay hơn và nên được chấp nhận. – kevinarpe

+0

Khi @Wolph chỉ ra câu trả lời của mình, giải pháp này không đảm bảo một tên nhất quán cho các tín hiệu trùng lặp. – tbc0

27

Với việc bổ sung các signal.Signalsenum bằng Python 3.5 giờ đây thật dễ dàng như:

>>> import signal 
>>> signal.SIGINT.name 
'SIGINT' 
>>> signal.SIGINT.value 
2 
>>> signal.Signals(2).name 
'SIGINT' 
>>> signal.Signals['SIGINT'].value 
2 
+1

Đây là một câu trả lời tuyệt vời cho người dùng Py3. –

0

B uilding trên another answer:

import signal 

if hasattr(signal, "Signals"): 
    def _signal_name(signum): 
     try: 
      return signal.Signals(signum).name 
     except ValueError: 
      pass 
else: 
    def _signal_name(signum): 
     for n, v in sorted(signal.__dict__.items()): 
      if v != signum: 
       continue 
      if n.startswith("SIG") and not n.startswith("SIG_"): 
       return n 

def signal_name(signum): 
    if signal.SIGRTMIN <= signum <= signal.SIGRTMAX: 
     return "SIGRTMIN+{}".format(signum - signal.SIGRTMIN) 
    x = _signal_name(signum) 
    if x is None: 
     # raise ValueError for invalid signals 
     signal.getsignal(signum) 
     x = "<signal {}>".format(signum) 
    return x 
Các vấn đề liên quan