2012-02-13 26 views
6

Tôi đã sinh ra một Greenlet và liên kết nó với một cuộc gọi. Một thời gian sau, Greenlet không thành công với ngoại lệ. Các cuộc gọi được liên kết được gọi. Đó là tất cả tuyệt vời!làm thế nào để chụp một traceback trong gevent

Đây là vấn đề:

Truy nguyên cho Ngoại lệ xuất hiện trên bảng điều khiển của tôi như bạn mong đợi. Nhưng tôi muốn làm những việc với sự truy nguyên đó trong cuộc gọi được liên kết. Làm cách nào để tôi có quyền truy cập vào lần truy cập đó trong cuộc gọi được liên kết?

(bản năng đầu tiên của tôi là sử dụng traceback.extract_stack(), nhưng nó chỉ ra rằng cung cấp một traceback cho bản thân callable liên kết và không cho ngoại lệ.)

Trả lời

15

Truy nguyên được cố tình không lưu khi Greenlet chết. Nếu nó đã được lưu, nó sẽ giữ rất nhiều đối tượng còn sống được dự kiến ​​sẽ bị xóa, điều quan trọng đặc biệt là nếu đối tượng quản lý một số tài nguyên (tệp mở hoặc ổ cắm).

Nếu bạn muốn lưu traceback, bạn phải tự mình thực hiện.

+1

Và đó là một câu trả lời có thẩm quyền. Cảm ơn, Denis. – kkurian

1

Chỉ cần chắc chắn rằng bạn lấy giá trị exception của Greenlet và ném nó ra ngoài Greenlet, ví dụ get lợi nhuận hoặc giá trị trả lại hoặc làm tăng Tế l ngoại lệ.

import traceback 
import gevent 

def fail(): 
    return 0/0 

gl = gevent.spawn(fail) 

try: 
    gl.get() 
except Exception as e: 
    stack_trace = traceback.format_exc() # here's your stacktrace 

Nên cung cấp cho bạn những gì bạn cần.

+0

Tôi đang cố gắng lấy lại dấu vết trong một liên kết có thể gọi được (ví dụ: foo = gevent.Greenlet (x); foo.link_exception (bar); foo.start(); ; ) - làm những gì bạn đã đề xuất trong bar() không tạo ra traceback cho Exception khi nó được nâng lên trong foo, nó tạo ra traceback cho Exception khi nó được nâng lên trong bar. – kkurian

+0

Có lẽ bạn nên dán mã của bạn lên trên, vấn đề của bạn dường như là một vấn đề phạm vi và sẽ dễ dàng hơn để gỡ lỗi nếu chúng ta có thể thấy cách bạn đang thiết lập phạm vi của mình. –

0

Là giải pháp thay thế cho giải pháp của Stephen Diehl sử dụng Greenlet.link_exception.

import traceback 

import gevent 

def job(): 
    raise Exception('ooops') 

def on_exception(greenlet): 
    try: 
     greenlet.get() 
    except Exception: 
     err = traceback.format_exc() 
     # Do something with `err` 

g = gevent.spawn(job) 
g.link_exception(on_exception) 
+0

Bạn sẽ sinh ra rồi liên kết chứ không phải tạo, liên kết và bắt đầu? Có sự khác biệt thực tế nào không? – kkurian

+0

Và điều này giải quyết được những lo ngại tôi nêu ra trong các nhận xét về giải pháp của Diehl? – kkurian

+0

Tôi đoán về mặt lý thuyết, greenlet có thể bị hỏng trước khi liên kết được tạo theo cách này. – renstrm

Các vấn đề liên quan