Description
When a thread (eg, one created by gevent.spawn
) raises an exception, an error is printed to stderr.
For example:
>>> import gevent
>>> def raise_error():
... raise Exception("oh no!")
>>> thread = gevent.spawn(raise_error)
>>> try: thread.get()
... except: pass
Traceback (most recent call last): # <<< error printed by gevent
...
Exception: oh no!
<Greenlet at 0x1022198d0: raise_error> failed with Exception
>>>
This is not always desirable (eg, in the case of expected exceptions) and can be confusing.
Reported by wolever.
Earlier Comments
Denis.Bilenko said, at 2010-10-29T04:13:44.000Z
This is by design.
There are many ways to send logs to wherever you want:
- catch the exceptions and log them yourself with try/except
- subclass Greenlet (complex)
- replace sys.stderr with your own object
- redirect stderr to another process which does the logging (trivial)
"python mygeventapp.py 2>&1 | /usr/bin/logger -t mygeventapp"
will log to syslog
In case of expected exceptions it's better to catch them. That way it will be obvious when reading the code that those exceptions are desirable.
wolever said, at 2010-10-29T04:27:41.000Z:
I agree that it's important to be able to log exceptions (especially in the context of threads which would otherwise disappear without a trace), but it would be nice to have some sort of defined interface for controlling where they go.
Additionally, it should be possible to ignore "expected" exceptions entirely so they don't add noise to the log.
If it would be considered useful, I'd be happy to bang together something simple. Say:
- A defined interface for "where exceptions get logged"
- Adding a flag to "join" which says "don't worry, I'm aware this might raise an exception"
- Ignoring (ie, not logging) exceptions raised as a result of a call to ".get()", as they will be re-raised anyway
Denis.Bilenko said, at 2010-10-29T05:03:26.000Z:
Additionally, it should be possible to ignore "expected" exceptions entirely so they don't add noise to the log.
There is already a way to do it: wrap you code with try/except return the exceptions you don't consider errors. There's even a helper function for that: http://gevent.org/gevent.util.html#gevent.util.wrap_errors
A defined interface for "where exceptions get logged
I don't think it's needed, but if stderr is not good for your needs, then consider subclassing Greenlet and rewriting the parts that write to stderr. Keep in mind then gevent writes to stderr in several places so rather than subclass them all it's better to handle stderr somehow (either redirect or monkey patch).
Adding a flag to "join" which says "don't worry, I'm aware this might raise an exception
join() is not the right place for this. Consider what will happen if the greenlet finishes before a call to join() is made.
Ignoring (ie, not logging) exceptions raised as a result of a call to ".get()", as they will be re-raised anyway
This would means there's a chance that the error is lost, because get() might be never called. The current system is dumb on purpose: there must be absolutely no chance that a greenlet dying of error goes unnoticed.