This is probably very basic, but it's giving me a headache, and I'm not sure what method to even approach it with, making the googling tough.
If开发者_如何学运维 I have a class in a module that I'm importing with various prints throughout, how can I read the prints as they come so that I may output them to a PyQT text label?
class Worker(QtCore.QThread, object):
class statusWrapper(object):
def __init__(self, outwidget):
self.widget = outwidget
def write(self, s):
self.widget.setText(s)
def __init__(self, widget):
QtCore.QThread.__init__(self)
sys.stdout = statusWrapper(widget)
def run(self):
self.runModule() #This is the module with the prints within.
Something mysterious gets passed to the statusWrapper.write when runModule gets executed, but it's blank. What am I doing wrong?
Thanks.
Instead of writing your own statusWrapper class, you could use a StringIO object as stdout. Something like:
def __init__(self, widget):
QtCore.QThread.__init__(self)
def run(self):
real_stdout = sys.stdout
sys.stdout = StringIO.StringIO()
self.runModule()
label_text = sys.stdout.getvalue()
sys.stdout = real_stdout
Restoring the original value of stdout is important for your sanity. Also note that this will not do what you expect in a multithreaded environment. Also note that delnan is certainly correct, and replacing stdout is an incredibly hackish way of doing this.
If you're wanting something which will update the label each time the module prints output (sort of a poor man's status indicator), there are better ways to do that too - you could replace the prints with calls to a callback function, which you set in the module when you import it, or something like that.
Something mysterious gets passed to the statusWrapper.write when runModule gets executed, but it's blank. What am I doing wrong?
It's nothing mysterious: write
just receives each string that was written to sys.stdout
(that is, your wrapper, in this case).
The bug is probably that the wrapper calls setText
only, replacing the widget's text on each write, instead of appending to it. You'll need to at least do something like:
def write(self, s):
self.widget.setText(self.widget.text() + s)
(or whatever the more efficient way is of appending text to a QT widget).
Note:
A much better way to redirect sys.stdout
is to use a context manager. PEP 343 defines the following example:
from contextlib import contextmanager
@contextmanager
def stdout_redirected(new_stdout):
save_stdout = sys.stdout
sys.stdout = new_stdout
try:
yield None
finally:
sys.stdout = save_stdout
You would use it like:
class Worker(QtCore.QThread, object):
def run(self):
with stdout_redirected(StatusWrapper(widget)):
self.runModule()
Besides being more readable, this context manager makes sure to restore sys.stdout if runModule
raises an exception (which is important for your sanity :-).
The easiest (still wrong - the right way is changing the function) way is redirecting stdout to the label (print writes to sys.stdout). See Wxwidgets and Pyqt for a trivial example with a QPlainTextEdit, should be easy to adjust for a QLabel.
精彩评论