Python đọc dữ liệu tín hiệu như thế nào?

Các hệ thống UNIX/Linux cung cấp các cơ chế đặc biệt để giao tiếp giữa từng tiến trình riêng lẻ. Một trong những cơ chế này là các tín hiệu, và thuộc về các phương thức giao tiếp khác nhau giữa các tiến trình (Inter Process Communication, viết tắt là IPC)

Nói tóm lại, tín hiệu là các ngắt phần mềm được gửi đến chương trình (hoặc quy trình) để thông báo cho chương trình về các sự kiện hoặc yêu cầu quan trọng đối với chương trình để chạy một chuỗi mã đặc biệt. Một chương trình nhận được tín hiệu sẽ dừng hoặc tiếp tục thực hiện các lệnh của nó, kết thúc có hoặc không có kết xuất bộ nhớ hoặc thậm chí đơn giản là bỏ qua tín hiệu

Mặc dù được định nghĩa trong tiêu chuẩn POSIX, phản ứng thực sự phụ thuộc vào cách nhà phát triển viết tập lệnh và triển khai xử lý tín hiệu

Trong bài viết này, chúng tôi giải thích tín hiệu là gì, chỉ cho bạn cách gửi tín hiệu đến một quy trình khác từ dòng lệnh cũng như xử lý tín hiệu nhận được. Trong số các mô-đun khác, mã chương trình chủ yếu dựa trên mô-đun tín hiệu. Mô-đun này kết nối các tiêu đề C tương ứng của hệ điều hành của bạn với thế giới Python

Giới thiệu về tín hiệu

Trên hệ thống dựa trên UNIX, có ba loại tín hiệu

  • Tín hiệu hệ thống (lỗi phần cứng và hệ thống). SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGKILL, SIGSEGV, SIGXCPU, SIGXFSZ, SIGIO

  • tín hiệu thiết bị. SIGHUP, SIGINT, SIGPIPE, SIGALRM, SIGCHLD, SIGCONT, SIGSTOP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH, SIGIO

  • Tín hiệu do người dùng xác định. SIGQUIT, SIGABRT, SIGUSR1, SIGUSR2, SIGTERM

Mỗi tín hiệu được biểu thị bằng một giá trị số nguyên và danh sách các tín hiệu khả dụng tương đối dài và không nhất quán giữa các biến thể UNIX/Linux khác nhau. Trên hệ thống Debian GNU/Linux, lệnh

$ kill -15 12345
2 hiển thị danh sách các tín hiệu như sau

$ kill -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

Các tín hiệu từ 1 đến 15 được chuẩn hóa đại khái và có ý nghĩa như sau trên hầu hết các hệ thống Linux

  • 1 (HÍT LÊN). chấm dứt kết nối hoặc tải lại cấu hình cho daemon
  • 2 (DẤU HIỆU). ngắt phiên từ trạm đối thoại
  • 3 (SIGQUIT). kết thúc phiên từ trạm đối thoại
  • 4 (SIGILL). hướng dẫn bất hợp pháp đã được thực hiện
  • 5 (SIGTRAP). thực hiện một hướng dẫn duy nhất (bẫy)
  • 6 (SIGABRT). sự chấm dứt bất thường
  • 7 (SIGBUS). lỗi trên bus hệ thống
  • 8 (SIGFPE). lỗi dấu phẩy động
  • 9 (SIGKILL). ngay lập tức chấm dứt quá trình
  • 10 (SIGUSR1). tín hiệu do người dùng xác định
  • 11 (SIGSEGV). lỗi phân đoạn do truy cập bất hợp pháp một đoạn bộ nhớ
  • 12 (SIGUSR2). tín hiệu do người dùng xác định
  • 13 (SIGPIPE). viết vào một đường ống, và không ai đọc từ nó
  • 14 (SIGALRM). bộ đếm thời gian kết thúc (báo thức)
  • 15 (SIGTERM). kết thúc quá trình một cách nhẹ nhàng

Để gửi tín hiệu đến một quy trình trong thiết bị đầu cuối Linux, bạn gọi lệnh

$ kill -15 12345
3 với cả số tín hiệu (hoặc tên tín hiệu) từ danh sách trên và id của quy trình (pid). Lệnh ví dụ sau gửi tín hiệu 15 (SIGTERM) đến quy trình có pid 12345

$ kill -15 12345

Một cách tương đương là sử dụng tên tín hiệu thay vì số của nó

$ kill -SIGTERM 12345

Bạn chọn cách nào tùy thuộc vào cách nào thuận tiện hơn cho bạn. Cả hai cách đều có tác dụng như nhau. Kết quả là quá trình nhận được tín hiệu SIGTERM và kết thúc ngay lập tức

Sử dụng Thư viện tín hiệu Python

Kể từ Python 1. 4, thư viện

$ kill -15 12345
4 là thành phần thông thường của mọi bản phát hành Python. Để sử dụng thư viện
$ kill -15 12345
4, trước tiên hãy nhập thư viện vào chương trình Python của bạn như sau

import signal

Việc nắm bắt và phản ứng đúng trên tín hiệu nhận được được thực hiện bằng chức năng gọi lại - cái gọi là trình xử lý tín hiệu. Một bộ xử lý tín hiệu khá đơn giản tên là

$ kill -15 12345
6 có thể được viết như sau

def receiveSignal(signalNumber, frame):
    print('Received:', signalNumber)
    return

Trình xử lý tín hiệu này không làm gì khác ngoài việc báo cáo số lượng tín hiệu nhận được. Bước tiếp theo là đăng ký các tín hiệu được bộ xử lý tín hiệu bắt. Đối với các chương trình Python, tất cả các tín hiệu (trừ 9, SIGKILL) có thể được bắt trong tập lệnh của bạn

Tiếp theo, chúng tôi thêm thông tin quy trình cho quy trình hiện tại và phát hiện id quy trình bằng methode

$ kill -15 12345
7 từ mô-đun
$ kill -15 12345
8. Trong một vòng lặp
$ kill -15 12345
9 vô tận, chúng tôi chờ đợi các tín hiệu đến. Chúng tôi triển khai điều này bằng cách sử dụng thêm hai mô-đun Python - os và time. Chúng tôi cũng nhập chúng vào đầu tập lệnh Python của mình

$ kill -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX
3

Trong vòng lặp

$ kill -15 12345
9 của chương trình chính của chúng ta, câu lệnh in xuất ra "Đang chờ. ". Lệnh gọi hàm
$ kill -SIGTERM 12345
1 khiến chương trình đợi trong ba giây

Hãy xem hướng dẫn thực hành, thực tế của chúng tôi để học Git, với các phương pháp hay nhất, tiêu chuẩn được ngành chấp nhận và bao gồm bảng gian lận. Dừng các lệnh Git trên Google và thực sự tìm hiểu nó

Cuối cùng, chúng ta phải kiểm tra kịch bản của mình. Đã lưu tập lệnh dưới dạng

$ kill -SIGTERM 12345
2, chúng ta có thể gọi nó trong một thiết bị đầu cuối như sau

$ kill -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX
7

Trong cửa sổ đầu cuối thứ hai, chúng tôi gửi tín hiệu đến quy trình. Chúng tôi xác định quy trình đầu tiên của mình - tập lệnh Python - theo id quy trình như được in trên màn hình, ở trên

$ kill -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX
8

Trình xử lý sự kiện tín hiệu trong chương trình Python của chúng tôi nhận tín hiệu mà chúng tôi đã gửi đến quy trình. Nó phản ứng tương ứng và chỉ cần xác nhận tín hiệu nhận được

$ kill -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX
9

Bỏ qua tín hiệu

Mô-đun tín hiệu xác định các cách để bỏ qua các tín hiệu nhận được. Để làm được điều đó, tín hiệu phải được kết nối với chức năng được xác định trước

$ kill -SIGTERM 12345
3. Ví dụ dưới đây chứng minh điều đó, và kết quả là chương trình Python không thể bị gián đoạn bởi
$ kill -SIGTERM 12345
4 nữa. Để dừng tập lệnh Python, một cách khác đã được triển khai trong tập lệnh ví dụ - tín hiệu SIGUSR1 chấm dứt tập lệnh Python. Hơn nữa, thay vì một vòng lặp vô tận, chúng tôi sử dụng phương pháp
$ kill -SIGTERM 12345
5. Nó chỉ chờ tín hiệu được nhận

Xử lý tín hiệu đúng cách

Trình xử lý tín hiệu mà chúng tôi đã sử dụng cho đến nay khá đơn giản và chỉ báo cáo tín hiệu đã nhận. Điều này cho chúng tôi thấy rằng giao diện của tập lệnh Python của chúng tôi đang hoạt động tốt. Hãy cải thiện nó

Bắt tín hiệu đã là một cơ sở tốt nhưng cần một số cải tiến để tuân thủ các quy tắc của tiêu chuẩn POSIX. Để có độ chính xác cao hơn, mỗi tín hiệu cần có phản ứng thích hợp (xem danh sách ở trên). Điều này có nghĩa là trình xử lý tín hiệu trong tập lệnh Python của chúng ta cần được mở rộng theo một quy trình cụ thể cho mỗi tín hiệu. Điều này hoạt động tốt nhất nếu chúng ta hiểu tín hiệu làm gì và phản ứng thông thường là gì. Quá trình nhận tín hiệu 1, 2, 9 hoặc 15 sẽ kết thúc. Trong bất kỳ trường hợp nào khác, dự kiến ​​​​cũng sẽ viết một kết xuất lõi

Cho đến bây giờ, chúng tôi đã triển khai một quy trình duy nhất bao gồm tất cả các tín hiệu và xử lý chúng theo cùng một cách. Bước tiếp theo là thực hiện một quy trình riêng cho mỗi tín hiệu. Mã ví dụ sau minh họa điều này cho các tín hiệu 1 (SIGHUP) và 15 (SIGTERM)

$ kill -15 12345
3

Hai chức năng trên được kết nối với các tín hiệu như sau

$ kill -15 12345
0

Chạy tập lệnh Python và gửi tín hiệu 1 (SIGHUP) theo sau là tín hiệu 15 (SIGTERM) bằng lệnh UNIX

$ kill -SIGTERM 12345
6 và
$ kill -SIGTERM 12345
7 dẫn đến đầu ra sau

$ kill -15 12345
1

Tập lệnh nhận tín hiệu và xử lý chúng đúng cách. Để rõ ràng, đây là toàn bộ kịch bản

Đọc thêm

Sử dụng mô-đun

$ kill -15 12345
4 và trình xử lý sự kiện phù hợp, việc bắt tín hiệu tương đối dễ dàng. Biết ý nghĩa của các tín hiệu khác nhau và để phản ứng đúng như được định nghĩa trong tiêu chuẩn POSIX là bước tiếp theo. Nó yêu cầu trình xử lý sự kiện phân biệt giữa các tín hiệu khác nhau và có một thói quen riêng cho tất cả chúng

Tín hiệu hoạt động như thế nào trong Python?

Trình xử lý tín hiệu Python luôn được thực thi trong luồng Python chính của trình thông dịch chính, ngay cả khi tín hiệu được nhận trong luồng khác . Điều này có nghĩa là tín hiệu không thể được sử dụng làm phương tiện liên lạc giữa các luồng. Thay vào đó, bạn có thể sử dụng các nguyên hàm đồng bộ hóa từ mô-đun luồng.

Python có thể được sử dụng để xử lý tín hiệu không?

Một trong những ưu điểm chính của Python là các gói có thể được sử dụng để mở rộng ngôn ngữ nhằm cung cấp các khả năng nâng cao như thao tác mảng và ma trận [5], xử lý ảnh [12] . [5], and visualization [7].

Python xử lý Ctrl C như thế nào?

Bạn có thể xử lý CTRL + C bằng cách bắt ngoại lệ KeyboardInterrupt. Bạn có thể triển khai bất kỳ mã dọn dẹp nào trong trình xử lý ngoại lệ. .
Chú ý khi sử dụng dung dịch này. .
điều này sẽ không hoạt động cho strg+d?.
Vấn đề với KeyboardInterrupt là, nó sẽ đưa bạn ra khỏi khối thử

Trình xử lý tín hiệu Python là gì?

Trình xử lý tín hiệu là hàm do người dùng xác định, trong đó các tín hiệu Python có thể được xử lý . Nếu chúng ta lấy tín hiệu SIGINT (Tín hiệu ngắt), hành vi mặc định sẽ là dừng chương trình đang chạy hiện tại. Tuy nhiên, chúng tôi có thể chỉ định một trình xử lý tín hiệu để phát hiện tín hiệu này và thay vào đó thực hiện xử lý tùy chỉnh của chúng tôi.