By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,360 Members | 2,961 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,360 IT Pros & Developers. It's quick & easy.

Redirect stdout & stderr (similar to a daemon)

P: n/a
Dear all,

I have a problem with a redirecting stdout and stderr. I am a top level
module and has no control over the imported modules that are making
system calls such as os.system or popen2.* . I have tried the simplest
method of capturing stdout, stderr via:

saveout = sys.stdout
sys.stdout = file_obj

print 1 # works
os.system('w') # Doesn't work

sys.stdout = saveout
print 1 # Restored

------------------------------------------------

Therefore, I changed to the following method, similar
to a daemon. However, I couldn't find a way to restore back stdout and
stderr.

import os
import sys

stdin = '/dev/null'
stdout = '/tmp/out.txt'
stderr = stdout

# Doesn't work
saveout = sys.stdout

si = file(stdin, 'r')
so = file(stdout, 'a+')
se = file(stderr, 'a+', 0)

# Redirect standard file descriptors.
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())

# Gets written to /tmp/out.txt
os.system('no_such_command')
os.system('w')
# How to do restoration of stdout and stderr
os.system('w')
print "Hello there"

Many thanks
Liming
Jul 18 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
In article <40******@news.starhub.net.sg>,
Tsai Li Ming <ma*********@ltsai.com> wrote:
I have a problem with a redirecting stdout and stderr. I am a top level
module and has no control over the imported modules that are making
system calls such as os.system or popen2.* . I have tried the simplest
method of capturing stdout, stderr via:

saveout = sys.stdout
sys.stdout = file_obj

print 1 # works
os.system('w') # Doesn't work
I think the problem here is that os.system runs a
shell with its own new set of process parameters,
including its own stdin, stdout, etc.

I would try one of the os.exec's or os.spawn's here
instead.
[ ... ]
# Redirect standard file descriptors.
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())


These modify the actual file objects represented by
'sys.stdin', etc. There's no coming back from that.

Regards. Mel.
Jul 18 '05 #2

P: n/a
Mel Wilson wrote:
In article <40******@news.starhub.net.sg>,
Tsai Li Ming <ma*********@ltsai.com> wrote:
I have a problem with a redirecting stdout and stderr. I am a top level
module and has no control over the imported modules that are making
system calls such as os.system or popen2.* . I have tried the simplest
method of capturing stdout, stderr via:

saveout = sys.stdout
sys.stdout = file_obj

print 1 # works
os.system('w') # Doesn't work

I think the problem here is that os.system runs a
shell with its own new set of process parameters,
including its own stdin, stdout, etc.

I would try one of the os.exec's or os.spawn's here
instead.

[ ... ]
# Redirect standard file descriptors.
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())

These modify the actual file objects represented by
'sys.stdin', etc. There's no coming back from that.

Regards. Mel.


I would think so too. Sadly, I can't use other system calls because I
will be importing other modules that I have no control of.

Liming
Jul 18 '05 #3

P: n/a
Tsai Li Ming wrote:
Dear all,

I have a problem with a redirecting stdout and stderr. I am a top level
module and has no control over the imported modules that are making
system calls such as os.system or popen2.* . I have tried the simplest
method of capturing stdout, stderr via:

saveout = sys.stdout
sys.stdout = file_obj

print 1 # works
os.system('w') # Doesn't work

sys.stdout = saveout
print 1 # Restored

------------------------------------------------

Therefore, I changed to the following method, similar
to a daemon. However, I couldn't find a way to restore back stdout and
stderr.


if I understand what you're looking to do, I solved a similar problem by
pushing the redirection of standard out and standard error into the
command that I executed.

baseline_command ="somecommand 2> <temporary filename> 1> /dev/null"

and then on executing the command, standard I/O is redirected in the
child process which eliminates the need to manipulate it in your
program. The program fragment below should get you started. As you can
see, it executes the command and then if the error file is non zero
length, you retrieve the data and do something with it. The same
technique can be applied to standard out just as easily.

command_pipe = os.popen(command, "w")
command_pipe.write(trapped_message.as_string(1))
result = command_pipe.close()

if os.path.getsize(error_path) != 0:
for line in file(error_path).readlines():
log("command error %s"% line)
os.remove(error_path)

hope this is close to what you need
Jul 18 '05 #4

P: n/a
Quoth mw*****@the-wire.com (Mel Wilson):
| In article <40******@news.starhub.net.sg>,
| Tsai Li Ming <ma*********@ltsai.com> wrote:
....
|> # Redirect standard file descriptors.
|> os.dup2(si.fileno(), sys.stdin.fileno())
|> os.dup2(so.fileno(), sys.stdout.fileno())
|> os.dup2(se.fileno(), sys.stderr.fileno())
|
| These modify the actual file objects represented by
| 'sys.stdin', etc. There's no coming back from that.

There is, if I understand what you meant by that. Consider

old0 = os.dup(0)
os.dup2(si.fileno(), 0)

The original input stream is held open on some arbitrary
unit, which you may use at any point to restore it to standard
input.

os.dup2(old0, 0)
os.close(old0)

Donn Cave, do**@drizzle.com
Jul 18 '05 #5

P: n/a
Donn Cave wrote:
Quoth mw*****@the-wire.com (Mel Wilson):
| In article <40******@news.starhub.net.sg>,
| Tsai Li Ming <ma*********@ltsai.com> wrote:
...
|> # Redirect standard file descriptors.
|> os.dup2(si.fileno(), sys.stdin.fileno())
|> os.dup2(so.fileno(), sys.stdout.fileno())
|> os.dup2(se.fileno(), sys.stderr.fileno())
|
| These modify the actual file objects represented by
| 'sys.stdin', etc. There's no coming back from that.

There is, if I understand what you meant by that. Consider

old0 = os.dup(0)
os.dup2(si.fileno(), 0)

The original input stream is held open on some arbitrary
unit, which you may use at any point to restore it to standard
input.

os.dup2(old0, 0)
os.close(old0)

Donn Cave, do**@drizzle.com


Thanks Donn,

Why is there a need to close old0? Because of the extra file handle?

Liming
Jul 18 '05 #6

P: n/a
Quoth Tsai Li Ming <ma*********@ltsai.com>:
| Donn Cave wrote:

| > There is, if I understand what you meant by that. Consider
| >
| > old0 = os.dup(0)
| > os.dup2(si.fileno(), 0)
| >
| > The original input stream is held open on some arbitrary
| > unit, which you may use at any point to restore it to standard
| > input.
| >
| > os.dup2(old0, 0)
| > os.close(old0)
| >
| > Donn Cave, do**@drizzle.com
|
| Thanks Donn,
|
| Why is there a need to close old0? Because of the extra file handle?

Good question. It's just barely conceivable that it could cause a
problem - say, where a child process redirects 0 but doesn't account
for the dup'd version, the parent exits, the file stays open when
it should have closed on exit, and something else has been depending
on that. To start with, most normal ways to fork a child process
will close all the extra files anyway, so this is highly improbable.

I would still do it, but it's more style than function.

Donn Cave, do**@drizzle.com
Jul 18 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.