blueFast
blueFast

Reputation: 44371

Get file object from file number

Let's say I have a list of the opened files (actually, of the file numbers):

import resource
import fcntl

def get_open_fds():
    fds = []
    soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
    for fd in range(3, soft):
        try:
            flags = fcntl.fcntl(fd, fcntl.F_GETFD)
        except IOError:
            continue
        fds.append(fd)
    return fds

Now I would like to get the names of those files. How can I do this?

EDIT

Just to clarify, for those downvoting this: fd is an integer. It is NOT a filedescriptor. Sorry for confusing you with the name, but the code is self-explanatory.

EDIT2

I am getting flamed about this, I think because of my choice of fd to mean file number. I just checked the documentation:

All functions in this module take a file descriptor fd as their first argument. This can be an integer file descriptor, such as returned by sys.stdin.fileno(), or a file object, such as sys.stdin itself, which provides a fileno() which returns a genuine file descriptor.

So fd is indeed an integer. It can also be a file object but, in the general case, fd has not .name.

Upvotes: 8

Views: 3985

Answers (2)

Ethan Furman
Ethan Furman

Reputation: 69041

I was in the same boat. What I ended up doing is writing my own open that keeps track of all the files opened. Then in the initial Python file the first thing that happens is the built-in open gets replaced by mine, and then later I can query it for the currently open files. This is what it looks like:

class Open(object):
    builtin_open = open
    _cache = {}
    @classmethod
    def __call__(cls, name, *args):
        file = cls.builtin_open(name, *args)
        cls._cache[name] = file
        return file
    @classmethod
    def active(cls, name):
        cls.open_files()
        try:
            return cls._cache[name]
        except KeyError:
            raise ValueError('%s has been closed' % name)
    @classmethod
    def open_files(cls):
        closed = []
        for name, file in cls._cache.items():
            if file.closed:
                closed.append(name)
        for name in closed:
            cls._cache.pop(name)
        return cls._cache.items()

import __builtin__
__builtin__.open = Open()

then later...

daemon.files_preserve = [open.active('/dev/urandom')]

Upvotes: 2

georg
georg

Reputation: 214959

As per this answer:

for fd in get_open_fds():
    print fd, os.readlink('/proc/self/fd/%d' % fd)

Upvotes: 7

Related Questions