Skip to main content
added 1421 characters in body
Source Link

If black_box merely calls open(file_path, mode) without further processing of file_path itself, you may be able to open the file yourself and pass a file descriptor:

black_box.do_something(open(file_path, mode).fileno())

black_box.do_something(open(file_path, mode).fileno())

If that works, you can capture the result of open() in a variable 'file', and when do_something() returns, you can just test 'file.closed' and call 'file.close()' if needed, before you remove the file.

If you are out of luck at this point and assuming that the part of black_box which actually opens the file is written in Python, you can also monkeypatch builtin.open, or os.open. Since you know the file name, the interception function checks the file name, and simply calls the original function if there is no match. When black_box opens the file, you recover the BufferedReader (or other Reader object) yourself, and you replace the method 'closed()' by your own.

The slightly more complex intercept of the low-level os.open function would look like this, but you cannot count on builtin.open actually calling os.open, and you'll have to experiment to find out how black_box opens the file.

import os    
real_open = os.open
real_close = os.close
FILENAME = "your file path"
SAVED_FD = None

def my_open(filename, flags, mode, *, dir_fd = None):
    if filename != FILENAME:
        return real_open(filename, flags, mode, dir_fd=dir_fd)
    fd = real_open(filename, flags, mode, dir_fd=dir_fd)
    SAVED_FD = fd
    return fd


import black_box
black_box.do_something(FILENAME)
if SAVED_FD is not None:
    try:
        os.close(SAVED_FD)
    except OSError:  # Bad file descriptor
        pass

Of course, all the capitalized globals can be local variables, or you might use contextvars in more complex cases.

If black_box merely calls open(file_path, mode) without further processing of file_path itself, you may be able to open the file yourself and pass a file descriptor:

black_box.do_something(open(file_path, mode).fileno())

If that works, you can capture the result of open() in a variable 'file', and when do_something() returns, you can just test 'file.closed' and call 'file.close()' if needed, before you remove the file.

If black_box merely calls open(file_path, mode) without further processing of file_path itself, you may be able to open the file yourself and pass a file descriptor:

black_box.do_something(open(file_path, mode).fileno())

If that works, you can capture the result of open() in a variable 'file', and when do_something() returns, you can just test 'file.closed' and call 'file.close()' if needed, before you remove the file.

If you are out of luck at this point and assuming that the part of black_box which actually opens the file is written in Python, you can also monkeypatch builtin.open, or os.open. Since you know the file name, the interception function checks the file name, and simply calls the original function if there is no match. When black_box opens the file, you recover the BufferedReader (or other Reader object) yourself, and you replace the method 'closed()' by your own.

The slightly more complex intercept of the low-level os.open function would look like this, but you cannot count on builtin.open actually calling os.open, and you'll have to experiment to find out how black_box opens the file.

import os    
real_open = os.open
real_close = os.close
FILENAME = "your file path"
SAVED_FD = None

def my_open(filename, flags, mode, *, dir_fd = None):
    if filename != FILENAME:
        return real_open(filename, flags, mode, dir_fd=dir_fd)
    fd = real_open(filename, flags, mode, dir_fd=dir_fd)
    SAVED_FD = fd
    return fd


import black_box
black_box.do_something(FILENAME)
if SAVED_FD is not None:
    try:
        os.close(SAVED_FD)
    except OSError:  # Bad file descriptor
        pass

Of course, all the capitalized globals can be local variables, or you might use contextvars in more complex cases.

Source Link

If black_box merely calls open(file_path, mode) without further processing of file_path itself, you may be able to open the file yourself and pass a file descriptor:

black_box.do_something(open(file_path, mode).fileno())

If that works, you can capture the result of open() in a variable 'file', and when do_something() returns, you can just test 'file.closed' and call 'file.close()' if needed, before you remove the file.