Filename for stdout
Grant Edwards
invalid at invalid.invalid
Wed Oct 20 23:58:42 EDT 2010
On 2010-10-21, James Mills <prologic at shortcircuit.net.au> wrote:
> On Thu, Oct 21, 2010 at 6:17 AM, Richard Gibbs
><richard.gibbs at smooth-stone.com> wrote:
>> If my python script is called with stdout (or stdin or stderr) redirected to
>> a file, how can I find the filename under Linux??? Under Windows?
>
> I don't believe there is a way to do this.
There is, but it's not pretty.
> The shell normally takes care of pipes.
And it takes care of redirects. Which, importantly for this case, are
not the same thing.
> When you do:
>
> $ ./foo > /tmp/foobar
>
> You're telling your shell to write the stdout output of foo to the
> file /tmp/foobar
Not quite. You're telling the shell to attach the file /tmp/foobar to
stdout before running the program foo. If the shell was reading data
from foo's stdout and then writing it to /tmp/foobar, we'd be out of
luck. But that's not what a redirect does.
> sys.stdout won't actually tell you anything useful. It's normally
> just a file descriptor.
Ah, but file descriptors _can_ tell you something useful. :)
The program below will print the filename(s) (if there are any) when
stdout is a regular file. NB: to make it easy to test, it only
searches below ".", so you'd probably want to widen the search if
you're doing this in a real program. [Asking sys.stdout for its
fileno is a bit redundant since it's defined to be 1 in the Unix
world.]
[I've no clue how to do this under Windows.]
[I also don't know what the answer is to the question the OP should
have asked. But, I suspect this is a case of asking for a method to
implement the wrong solution to an unstated problem.]
In any case, here's how do do "the wrong thing":
------------------------------------------------------------------------
#!/usr/bin/python
import sys,os,stat
write = sys.stderr.write
# search for file(s) with given device/inode values
def findFile(dev,ino):
namelist = []
for root,dirs,files in os.walk("."):
for name in files:
path = os.path.join(root,name)
statinfo = os.stat(path)
fdev,fino = statinfo[stat.ST_DEV],statinfo[stat.ST_INO]
if (dev,ino) == (fdev,fino):
namelist.append(path)
return namelist
# get stat info of stdout, and if it's a regular file, search
# filesystem under '.' for matching file(s)
fd = sys.stdout.fileno()
statinfo = os.fstat(fd)
mode = statinfo[stat.ST_MODE]
if stat.S_ISCHR(mode):
write("stdout is a char device\n")
elif stat.S_ISREG(mode):
dev,ino = statinfo[stat.ST_DEV],statinfo[stat.ST_INO]
write("stdout is a regular file on device %d inode %d\n" % (dev,ino))
write("filename(s): %s\n" % findFile(dev,ino))
elif stat.S_ISSOCK(mode):
write("stdout is a socket\n")
elif stat.S_ISFIFO(mode):
write("stdout is a FIFO\n")
else:
write("stdout unknown type\n")
More information about the Python-list
mailing list