0

I want to use a legacy function that receives a filename as an argument. The function will make some processing after opening that file.

def legacy_f(filename):
    with open(filename, 'r') as fh:
        # some processing

But I want the processing to happen in some data that is loaded in some variable already, not in a file. Saving the data to a file first is not a solution due to performance. Is there a way to "fool" the legacy function to make it think it is opening a file?

My situation is exactly the one in this question, but the accepted answer there recommends the use of tempfile.NamedTemporaryFile, which (I believe) does create a file in the disk. I can't afford that.

1 Answers1

2

Well this is a bit hacky and probably not a good practice but it you could monkey patch the open function within a context manager. This wont replace open, but simply patch it with something else within that context manager. you can see if i call the function again but outside the context manager it reverts back to using the builtin open.

However this type of mocking is usually used for testing.

from unittest import mock


def legacy_f(filename):
    with open(filename, 'r') as fh:
        for line in fh:
            print(line, end="")
        print()

data = "this\nis\nsome\ndata"
filename = "somefile"

#patch the open call
with mock.patch('builtins.open', mock.mock_open(read_data=data)):
    legacy_f(filename)

#the patch only works in the conext manager, outside its the normal open
try:
    legacy_f(filename)
except FileNotFoundError:
    print(f"file '{filename}' not found since we only patch in the context manager")

OUTPUT

this
is
some
data
file 'somefile' not found since we only patch in the context manager
Chris Doyle
  • 10,703
  • 2
  • 23
  • 42