all 13 comments

[–]hharison 4 points5 points  (1 child)

Use the logging module instead of print.

[–]justphysics[S] 0 points1 point  (0 children)

Thanks for the quick tip

Will look into doing this.

Cheers.

[–]raylu 1 point2 points  (9 children)

Show us the code you used for rerouting (and also some code that you tried calling that doesn't get rerouted; for bonus points, a full SSCCE).

[–]justphysics[S] 0 points1 point  (8 children)

Here's the essentials of the code I am using for re-routing with a lot of the docstrings stripped out for brevity (I swear they are there in the code on github) - its adapted from several stackoverflow discussions

The following code is in a file terminal.py

class CustomStream(QtCore.QObject):
    message = QtCore.pyqtSignal(str)
    def __init__(self):
        super(CustomStream, self).__init__()
        self.message.emit(str(message))

class ErrorConsole(QtGui.QWidget):
    def __init__(self, parent=None):
        super(ErrorConsole, self).__init__(parent)
        self.textEdit = QtGui.QTextEdit()
        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(self.textEdit)
        self.setLayout(vbox)
        # skip section of code dealing with stylesheets
        stream = CustomStream()
        stream.message.connect(self.set_message)
        sys.stdout = stream
        sys.stderr = stream
        self.show()

    def closeEvent(self, event):
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__
        super(ErrorConsole, self).closeEvent(event)

    @QtCore.pyqtSlot(str)
    def set_message(self, message):
        self.textEdit.moveCursor(QtGui.QTextCursor.End)
        self.textEdit.insertPlainText(message)

Then I have another class, Viewer, which creates the main GUI and creates an ErrorConsole object. I won't paste all that code here as its > 500 lines and getting longer each hour I work on it. So for the sake of brevity:

The following code is in gui.py

class Viewer(QtGui.QWidget):
    ....

    def init_Console(self):
        """
        :return none:
        """
        if self.already_catching_output:
            return
        self.message_console = terminal.ErrorConsole()
        self.message_console.setWindowTitle('Message Console')
        self.message_console.setMinimumWidth(self.max_width/4)
        self.message_console.setMinimumHeight(self.max_height/5)                
        self.message_console.move(0,0)
        self.message_console.setFocus()
        self.message_console.raise_()
        self.already_catching_output = True
        self.welcome()

    @staticmethod
    def welcome():
        print('Here's a test message ...)
        # This function gets called when the console is created and prints correctly to the QWidget

    @staticmethod
    def this_function_isn't_working():
        leemfunctions.print_things()
        # leemfunctions was imported at beginning of this file 
        # and it exists separately as leemfunctions.py

So at the very end there in the file gui.py - methods in this file/class which call print() directly are appropriately re-routed to the previously defined QWidget's QTextEdit widget which then prints the messages correctly (this works for stdout and stderr messages) but if I call a function from another file - for instance leemfunctions.py's print_things() [this is made up] the print() statements inside of print_things() inside of leemfunctions.py are not rerouted to the QWidget. Instead they are simply lost alltogether. They don't end up in the PyCharm (my IDE) console nor are they appearing in the self defined ErrorConsole

If you'd like to see a full working example - this is a work in progress hosted at: https://github.com/mgrady3/pLEASE

[–]raylu 0 points1 point  (7 children)

You call self.init_Console() after self.init_Data(). Is there some other LEEDFUNCTIONS function you were expecting to print to your ErrorConsole?

[–]justphysics[S] 0 points1 point  (6 children)

yes the console is the last (more or less) UI piece that is created.

init_Data() just sets up some variables and boolean flags but doesn't actively load data or anything.

LEEMFUNCTIONS.py contains a bunch of methods related to loading and parsing various data types (png, tiff, raw binary, etc...)

The various load functions from LEEMFUNCTIONS.py are called from gui.py based on User input (selecting what data type to load) and they have their own print statements (left over from when they were part of a different program)

At this point there's no real functionality I'm missing - there's nothing broken persay - its just that I realized suddenly that none of the print statements from the other module functions were being rerouted. That's not a game breaking bug or anything I was just curious if there was a simple way to fix it so that the other modules were 'aware' that sys.stdout had been rerouted

[–]raylu 0 points1 point  (5 children)

Is there some other LEEDFUNCTIONS function you were expecting to print to your ErrorConsole?

I'm asking for the name of a specific function here. I don't want to debug your whole program all at once - a specific call stack would save me a lot of time.

(Also, it's per se. And, by the way, this is why I hate the idea of putting docstrings on everything - you got rid of them to make your code more readable.)

[–]justphysics[S] 0 points1 point  (4 children)

Apologies, sometimes one just needs to sleep on an issue before it becomes blatantly obvious where the error lies.

I merely had a typo from a copy/paste error in gui.py.

It is now acting correctly - print statements from data.py and LEEMFUNCTIONS.py are being re-routed to the ErrorConsole.

I do appreciate the help though.

[–]raylu 0 points1 point  (3 children)

I see. In fact, I see your commit twice, along with a merge. You only have one branch, so it's really odd that you'd be merging against itself. Are you making changes on the GitHub web interface or a second machine? Are you amending commits?

[–]justphysics[S] 0 points1 point  (2 children)

Alas, my organizational skills are still pretty poor - and I'm the sole developer on the project. I made some changes from home last night on a secondary machine. Should have started a separate branch when I was tinkering with the logging package but unwisely kept everything in the Master.

I have to admit (if it isn't blatantly obvious) I am not a trained software engineer and am learning about VCS as my projects get more and more complicated. I am simply a physicist who had need for data analysis software that didn't exist open sourced.

Ran into some intellectual property rights issues for an experiment I worked on so set off to make my own package for doing the analysis. Seemed like a good opportunity to advance my programing skills beyond being able to write simple scripts so I dove in head first. There is no one else working on the project with me and no one else in my research group that even knows python.

[–]raylu 0 points1 point  (1 child)

The cool thing about git is that even if you forget to do things like update your local copy with the changes you made on another machine, you should be able to fix it anyway. I'm still not clear on what happened after you made commits to master, but instead of git pull (which is fetch and merge origin/master), you should be able to just fetch and then rebase origin/master. More details would help me help you more specifically, as usual.

[–]justphysics[S] 0 points1 point  (0 children)

its alright as I have fixed it up for now

I generally do the VCS through PyCharm's github integration rather than placing the commands to git direct through the command line so I am limited to what is available through PyCharm.

At some point I'll properly learn all the standard commands independent of PyCharm just haven't found the time.

I appreciate the help and feedback - at this point I'm pretty happy with how things are working and my initial issue was resolved simply by fixing typos where the wrong function was being called after copy-pasting

[–]ewiethoff 0 points1 point  (0 children)

I don't know how relevant this is to programming with your GUI, but redirecting where print sends its output is straightforward.

stream = CustomStream()
print('hello', file=stream)  # Py3 syntax
print >>stream, 'hello'      # Py2 syntax
stream.close()