Redirecting sys.stdout

Hello dear list users,

I have a problem when redirecting sys.stdout to a text control.

When I try to split the string from sys.stdout I get a list 'words 'as
expected. Iterating over the list via 'for word in words:' or via 'for i
in range(len(words)):' works fine. The error occurs if I try to
reference the listelements directly. If I call 'words[i]', 0 <= i <=
len(words), I get an error for some i. For which i this error occurs,
seems to change with each application run.

What I'm trying to achieve: Create a progress bar for a module, without
changing the module. I wrote a program that contains print statements to
indicate progress. I want to catch these print commands and create a
progress bar from them. I know I could just change my program to check
if it was run from gui or not, but I'd like to keep the logic and the
gui seperated as much as possible.

Minimal Example is attached.

The error occurs in Python 2.5.2 on Ubuntu 8.04 and Windows XP

minexample.py (2.32 KB)

Hello John,

John Gerdeman wrote:

Hello dear list users,

I have a problem when redirecting sys.stdout to a text control.

When I try to split the string from sys.stdout I get a list 'words 'as
expected. Iterating over the list via 'for word in words:' or via 'for i
in range(len(words)):' works fine. The error occurs if I try to
reference the listelements directly. If I call 'words[i]', 0 <= i <=
len(words), I get an error for some i. For which i this error occurs,
seems to change with each application run.
  

I did not check your script but you should use 'words[i]' where 0 <= i *<* len(words) instead of the secon <=.
Mathias

···

What I'm trying to achieve: Create a progress bar for a module, without
changing the module. I wrote a program that contains print statements to
indicate progress. I want to catch these print commands and create a
progress bar from them. I know I could just change my program to check
if it was run from gui or not, but I'd like to keep the logic and the
gui seperated as much as possible.

Minimal Example is attached.

The error occurs in Python 2.5.2 on Ubuntu 8.04 and Windows XP

Hi John,

Try inserting the following line in your 'write_2' method, before
anything else:

        sys.__stdout__.write(repr(string) + '\n')

With that in place, your program displays this:

'Processing step 1 of 50'
' '

...before the traceback. The print statement is actually calling 'write'
twice - the first time with the string that you printed, and the second
time with a space because your print statement has a trailing comma. If
you remove the trailing comma, the space becomes a newline instead.

To fix the problem, you could add a check in your 'write' method to see
whether the string is what you expect.

Eg:

  if string.startswith('Processing step '):
      words = string.split()
      <etc.>

Hope that helps,

Simon

···

-----Original Message-----
From: wxpython-users-bounces@lists.wxwidgets.org
[mailto:wxpython-users-bounces@lists.wxwidgets.org] On Behalf
Of John Gerdeman
Sent: 05 November 2008 14:25
To: wxpython-users@lists.wxwidgets.org
Subject: [wxpython-users] Redirecting sys.stdout

Hello dear list users,

I have a problem when redirecting sys.stdout to a text control.

When I try to split the string from sys.stdout I get a list 'words 'as
expected. Iterating over the list via 'for word in words:' or
via 'for i
in range(len(words)):' works fine. The error occurs if I try to
reference the listelements directly. If I call 'words[i]', 0 <= i <=
len(words), I get an error for some i. For which i this error occurs,
seems to change with each application run.

What I'm trying to achieve: Create a progress bar for a
module, without
changing the module. I wrote a program that contains print
statements to
indicate progress. I want to catch these print commands and create a
progress bar from them. I know I could just change my program to check
if it was run from gui or not, but I'd like to keep the logic and the
gui seperated as much as possible.

Minimal Example is attached.

The error occurs in Python 2.5.2 on Ubuntu 8.04 and Windows XP

I meant to mention this before - if your reason for doing this is to
keep GUI and logic separate, a pattern I tend to use in this situation
is something like:

def default_progress_callback(stage, step, total):
    print "%s: Processing step %d of %d" % (stage, step, total)

def long_operation(progress_callback=default_progress_callback):
    max = 50
    for i in range(1, max + 1):
        progress_callback('Stage 1', i, max)

    for i in range(1, max + 1):
        progress_callback('Stage 2', i, max)

Then in your GUI code, you can pass in a different callback function. I
have a helper object for this, so your calling code just has to look
like:

progress = ProgressWindow(self, 'Frobbing the foobar', 'Processing %s')
try:
   long_operation(progress_callback=progress.update)
finally:
   progress.destroy()

See the attached file for an example (pass 'gui' as a command line
parameter to see the gui version)

Hope that helps,

Simon

minexample2.py (2.46 KB)

···

-----Original Message-----
From: wxpython-users-bounces@lists.wxwidgets.org
[mailto:wxpython-users-bounces@lists.wxwidgets.org] On Behalf
Of King Simon-NFHD78
Sent: 05 November 2008 14:38
To: wxpython-users@lists.wxwidgets.org
Subject: RE: [wxpython-users] Redirecting sys.stdout

> -----Original Message-----
> From: wxpython-users-bounces@lists.wxwidgets.org
> [mailto:wxpython-users-bounces@lists.wxwidgets.org] On Behalf
> Of John Gerdeman
> Sent: 05 November 2008 14:25
> To: wxpython-users@lists.wxwidgets.org
> Subject: [wxpython-users] Redirecting sys.stdout
>
> Hello dear list users,
>
> I have a problem when redirecting sys.stdout to a text control.
>
> When I try to split the string from sys.stdout I get a list
'words 'as
> expected. Iterating over the list via 'for word in words:' or
> via 'for i
> in range(len(words)):' works fine. The error occurs if I try to
> reference the listelements directly. If I call 'words[i]', 0 <= i <=
> len(words), I get an error for some i. For which i this
error occurs,
> seems to change with each application run.
>
> What I'm trying to achieve: Create a progress bar for a
> module, without
> changing the module. I wrote a program that contains print
> statements to
> indicate progress. I want to catch these print commands and create a
> progress bar from them. I know I could just change my
program to check
> if it was run from gui or not, but I'd like to keep the
logic and the
> gui seperated as much as possible.
>
> Minimal Example is attached.
>
> The error occurs in Python 2.5.2 on Ubuntu 8.04 and Windows XP
>

Hi John,

Try inserting the following line in your 'write_2' method, before
anything else:

        sys.__stdout__.write(repr(string) + '\n')

With that in place, your program displays this:

'Processing step 1 of 50'
' '

...before the traceback. The print statement is actually
calling 'write'
twice - the first time with the string that you printed, and
the second
time with a space because your print statement has a trailing
comma. If
you remove the trailing comma, the space becomes a newline instead.

To fix the problem, you could add a check in your 'write'
method to see
whether the string is what you expect.

Eg:

  if string.startswith('Processing step '):
      words = string.split()
      <etc.>

Hope that helps,

Simon