Skip to main content
gamedev.net
🔒 Locked

Rerouting stderr in Python

Started by cow_in_the_well Dec 23, 2004 at 4:08 AM 14 replies 3.6k views
Original Post
cow_in_the_well
cow_in_the_well
Hi, I'm trying to reroute stderr and stdout in python to my ingame console. It's working for stdout but not stderr! >_<

# Lets override stdout/stdin/stderr NOW
import sys
import engine

class ConRedirect(object):
    @staticmethod
    def write(s):
        engine.ConPrint(s)
        
sys.stdout = ConRedirect()
sys.stderr = ConRedirect()

print ("blah")
somethingthatdoesntexist.lol # cause a runtime error
After running that code, print("blah") will be rerouted to engine.ConPrint, but stderr doesn't seem to get called at all (no traceback mesages get displayed, not even to the default console). If I comment out the line sys.stderr = stdoutRedirect() then it gets displayed as normal. This is quite frustrating as besides this, embedding python is going quite well. Any clues? Thanks.
cow_in_the_well
cow_in_the_well
Playing around some more, I found that if i did:

sys.stderr = open("ilikepie.txt", "w+")


The traceback report is correctly outputted to the file. What the hell is going on ??? >___<
cow_in_the_well
cow_in_the_well
Okay. After dreaming about this problem all night (one of the really annoying frustration dreams), I still can't work it out. I've discovered that when I do this:

class ConRedirect:    def write(self, s):        try:            engine.ConPrint(s)        except:                        print("Exception: " + s)


The except: code path gets executed while displaying a stderr! I'm not throwing any exception from engine.ConPrint(s). In fact, if i put a breakpoint in my engine.ConPrint function (implemented in C++) it never even gets called!

WTF >_<
Fruny
Fruny
Quote:
Original post by cow_in_the_well
The except: code path gets executed while displaying a stderr! I'm not throwing any exception from engine.ConPrint(s). In fact, if i put a breakpoint in my engine.ConPrint function (implemented in C++) it never even gets called!


The Python -> C++ interface itself might be borked. Re-check your binding code.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
cow_in_the_well
cow_in_the_well
well, if i call engine.ConPrint("blah") directly, it works. And if I bind ConRedirect to stdout then print("blah") works. Its only with stderr. :(
Fruny
Fruny
Quote:
Original post by cow_in_the_well
well, if i call engine.ConPrint("blah") directly, it works. And if I bind ConRedirect to stdout then print("blah") works. Its only with stderr. :(


Just stderr, or when you redirect both stdout and stderr?
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
cow_in_the_well
cow_in_the_well
I'm currently only redirecting stderr, since if i was redirecting stdout and used print() in ConRedirect it'd get into an infinite loop ;). So yeah, I'm currently only trying to get stderr to work (redirecting stdout to engine.ConPrint works).
Fruny
Fruny
I forgot to ask, what exception do you get?
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
cow_in_the_well
cow_in_the_well
Hmn. I can't get it to display the exception:

class ConRedirect:    def write(self, s):        try:            engine.ConPrint(s)            except:                        print("Exception: " + sys.exc_info())


Nothing gets displayed. Also, i just tried calling stderr directly, and it prints it out correctly (no exception).

sys.stderr = ConRedirect()sys.stderr.write("damnit")


Thanks
Fruny
Fruny
Care to post your C++ code somewhere so I can try it out,
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
cow_in_the_well
cow_in_the_well
Okay here it is: http://www.packetfrag.com/PyTest.zip

Its just a experiment app, so its a little messy, but its small enough to see whats going on.

init.py is where i'm doing the python side hookups...

Thanks [smile]
Fruny
Fruny
After mucking around a bit with portability (system("pause"), and a stray goto skipping variable initialization) and version issues (no decorators in 2.3), the output is

wtflolHARdamnit


No exceptions is thrown.

Gentoo Linux 2.6.8, python 2.3.4
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
cow_in_the_well
cow_in_the_well
thats exactly the point. The error being raised by accesssing somethingthatdoesntexist SHOULD be getting displayed, but it's not. Comment out sys.stderr = ConRedirect() to see what should get outputted.

Oh, and I'm using python 2.4
Fruny
Fruny
Quote:
Original post by cow_in_the_well
thats exactly the point. The error being raised by accesssing somethingthatdoesntexist SHOULD be getting displayed, but it's not. Comment out sys.stderr = ConRedirect() to see what should get outputted.


Ah, *hem*, I had taken that bit out. The traceback is printed out through the redirected stderr just fine.

Quote:
Oh, and I'm using python 2.4


I had guessed, from your use of function decorators ;)

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
cow_in_the_well
cow_in_the_well
ehhh....thats just weird. Bleh. This has burnt me out for the day, I might try it with python 2.3, although that shouldn't matter. I dug through the IDLE lib python code and copied exactly how they are redirecting and it still doesnt work o_O.

Thanks for the help Fruny.
cow_in_the_well
cow_in_the_well
Okay, thanks to SHilbert, the problem is solved :).

I was rerouting stderr and stdout in the same module i was raising a runtime error (for testing). This was all invoked by calling PyImport_ImportModule("init"). So, there was an exception during the import so python is deinitializing the module and returning. When i go to print the error with PyErr_Print(), its calling the ConRedirect::write function inside the now "derelict" init module.

If i let init.py run to completion, then call another module test.py, and cause an error in there, then it all works fine. If that at all makes sense o_o.

Damn. What an obscure error to trace [smile]

Thanks all...

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.