redirecting stdout and stderr to /dev/null
Jim Dodgen
jim at dodgen.us
Sat May 7 19:54:01 EDT 2016
*Thanks for the help*
On Sat, May 7, 2016 at 12:16 PM, Martin A. Brown <martin at linux-ip.net>
wrote:
>
> Hello there,
>
> >I'm new to python but well versed on other languages such as C and
> >Perl
> >
> >I'm have problems redirecting stdout and stderr to /dev/null in a
> >program that does a fork and exec. T found this method googling
> >around and it is quite elegant compared to to the Perl version.
> >
> >So to isolate things I made a much shorter test program and it
> >still is not redirecting. What am I doing wrong?
> >
> >test program test.py
> >----------------- cut here -------------------
> >import sys
> >import os
> >
> >f = open(os.devnull, 'w')
> >sys.stdout = f
> >sys.stderr = f
> >os.execl("/bin/ping", "", "-w", "20", "192.168.1.1");
> >------------------ cut here -------------------
>
> Think about the file descriptors.
>
> Unix doesn't care what the name is, rather that the process inherits
> the FDs from the parent. So, your solution might need to be a bit
> more complicated to achieve what you desire. Run the following to
> see what I mean.
>
> realstdout = sys.stdout
> realstderr = sys.stderr
> f = open(os.devnull, 'w')
> sys.stdout = f
> sys.stderr = f
>
> print("realstdout FD: %d" % (realstdout.fileno(),), file=realstdout)
> print("realstderr FD: %d" % (realstderr.fileno(),), file=realstdout)
> print("sys.stdout FD: %d" % (sys.stdout.fileno(),), file=realstdout)
> print("sys.stderr FD: %d" % (sys.stderr.fileno(),), file=realstdout)
>
> That should produce output that looks like this:
>
> realstdout FD: 1
> realstderr FD: 2
> sys.stdout FD: 3
> sys.stderr FD: 3
>
> I hope that's a good hint...
>
> I like the idea of simply calling the next program using one of the
> exec() variants, but you'll have to adjust the file descriptors,
> rather than just the names used by Python.
>
> If you don't need to exec(), but just run a child, then here's the
> next hint (this is for Python 3.5):
>
> import subprocess
> cmd = ["ping", "-w", "20", "192.168.1.1"]
> devnull = subprocess.DEVNULL
> proc = subprocess.run(cmd, stdout=devnull, stderr=devnull)
> proc.check_returncode()
>
> (By the way, your "ping" command looked like it had an empty token
> in the second arg position. Looked weird to me, so I removed it
> in my examples.)
>
The empty token is needed but useless, it is arg[0] most people just repeat
the program name
>
> For subprocess.run, see:
>
> https://docs.python.org/3/library/subprocess.html#subprocess.run
>
> For earlier Python versions without run(), you can use Popen():
>
> import subprocess
> cmd = ["/bin/ping", "-w", "20", "192.168.1.1"]
> devnull = subprocess.DEVNULL
> proc = subprocess.Popen(cmd, stdout=devnull, stderr=devnull)
> retcode = proc.wait()
> if retcode != 0:
> raise FlamingHorribleDeath
>
> You will have to define FlamingHorribleDeath or figure out what you
> want to do in the event of the various different types of
> failure....if you don't then, you'll just see this:
>
> NameError: name 'FlamingHorribleDeath' is not defined
>
> Good luck,
>
> -Martin
>
> --
> Martin A. Brown
> http://linux-ip.net/
seems not to find subprocess.DEVNULL
I'm on 2.7.6 Ubuntu, and 2.7.9 on Raspbian I expect I need 3.5
here are some Tracebacks I get, the second one is when I tried os.devnull
in place of subprocess.DEVNULL
Traceback (most recent call last):
File "test.py", line 5, in <module>
devnull = subprocess.DEVNULL
AttributeError: 'module' object has no attribute 'DEVNULL'
Traceback (most recent call last):
File "test.py", line 6, in <module>
proc = subprocess.Popen(cmd, stdout=os.devnull, stderr=os.devnull)
File "/usr/lib/python2.7/subprocess.py", line 702, in __init__
errread, errwrite), to_close = self._get_handles(stdin, stdout, stderr)
File "/usr/lib/python2.7/subprocess.py", line 1128, in _get_handles
c2pwrite = stdout.fileno()
AttributeError: 'str' object has no attribute 'fileno'
One other observation it looks as Popen behaves the same way as my fork
exec would
More information about the Python-list
mailing list