2013-02-05 18 views
7

Tôi đang chạy một số mô phỏng tính toán nặng trong các phần mở rộng python dựa trên C (tự tạo). Thỉnh thoảng tôi nhận được công cụ sai và muốn chấm dứt một mô phỏng. Tuy nhiên, Ctrl-C dường như không có hiệu ứng nào (ngoài việc in ^C vào màn hình để tôi phải hủy quá trình sử dụng kill hoặc theo dõi hệ thống.Cho phép Ctrl-C làm gián đoạn một phần mở rộng C python

Theo như tôi có thể thấy python chỉ đợi cho C mở rộng để kết thúc và không thực sự giao tiếp với nó trong thời gian này.

có cách nào để làm cho công việc này?

+0

Xem http://stackoverflow.com/questions/1112343/how-do-i-capture-sigint-in-python – user1929959

+0

liên quan: [CTRL + C không gián đoạn gọi điện để chia sẻ -library sử dụng CTYPES trong Python] (http://stackoverflow.com/q/14271697/4279) – jfs

Trả lời

2

tôi sẽ thiết kế lại các phần mở rộng C để họ không chạy trong một thời gian dài

Vì vậy, hãy chia chúng thành các bước cơ bản hơn (mỗi bước chạy trong một khoảng thời gian ngắn, ví dụ: 10 đến 50 mili giây) và có các bước cơ bản hơn này được gọi bằng mã Python.

continuation passing style thể có liên quan để hiểu, như một phong cách lập trình ...

+3

Xin lỗi, không phải là một tùy chọn nào trong trường hợp này :) Đó là một mô phỏng với một số lượng lớn các bước và tốc độ là điều cần thiết. Interfacing với python ở mỗi bước (hoặc thậm chí đều đặn) sẽ làm hỏng hiệu quả. –

+0

Cố gắng sắp xếp các bước vào thứ gì đó kéo dài một vài phần nghìn giây. Sau đó, chi phí đi đến Python là không đáng kể ... –

+0

Đó chắc chắn là giá trị suy nghĩ về, nhưng nó làm tăng rất nhiều vấn đề với quản lý bộ nhớ vv Cảm ơn! –

6

Python có một xử lý tín hiệu được cài đặt trên SIGINT mà chỉ đơn giản đặt một lá cờ đó được kiểm tra bởi các vòng lặp thông dịch viên chính. Để trình xử lý này hoạt động đúng, trình thông dịch Python phải đang chạy mã Python.

Bạn có một vài tùy chọn có sẵn cho bạn:

  1. Sử dụng Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS để giải phóng GIL xung quanh đang mở rộng C của bạn. Bạn không thể sử dụng bất kỳ hàm Python nào khi không giữ GIL, nhưng mã Python (và mã C khác) có thể chạy đồng thời với chuỗi C của bạn (đa luồng thực). Một chuỗi Python riêng biệt có thể thực thi cùng với phần mở rộng C và nắm bắt các tín hiệu Ctrl + C.
  2. Thiết lập trình xử lý tín hiệu SIGINT của riêng bạn và gọi trình xử lý tín hiệu gốc (Python). Trình xử lý SIGINT của bạn sau đó có thể thực hiện bất kỳ điều gì cần làm để hủy mã mở rộng C và trả về điều khiển cho trình thông dịch Python.
+0

(1) [phát hành GIL sẽ làm cho bất kỳ sự khác biệt chỉ khi phần mở rộng C chạy trong một chủ đề nền] (http://stackoverflow.com/q/14271697/4279). (2) [gọi 'Py_Err_CheckSignals()' thay vì manuall gọi trình xử lý tín hiệu Python] (http://stackoverflow.com/a/33652496/4279) – jfs

5

Tuy nhiên, Ctrl-C dường như không có bất kỳ tác

Ctrl-C in the shell sends SIGINT to the foreground process group. python khi nhận tín hiệu đặt cờ trong mã C. Nếu phần mở rộng C của bạn chạy trong luồng chính thì không có trình xử lý tín hiệu Python nào sẽ chạy (và do đó bạn sẽ không thấy ngoại lệ KeyboardInterrupt trừ PyErr_CheckSignals() kiểm tra cờ và chạy trình xử lý tín hiệu Python nếu cần hoặc nếu mô phỏng của bạn cho phép mã Python thực thi (ví dụ, nếu mô phỏng sử dụng các cuộc gọi lại Python). Nếu phần mở rộng chạy trong một chủ đề nền thì nó đủ để giải phóng GIL (để cho phép mã Python chạy trong luồng chính cho phép trình xử lý tín hiệu chạy).

liên quan: Cython, Python and KeybordInterrupt ingored