matanc1
matanc1

Reputation: 7023

receive file object or file path

I know that in static languages it's always better to receive a file object rather than a string representing a path (from a software design standpoint). However, in a dynamic language like python where you can't see the type of the variable, what's the "correct" way to pass a file?

Isn't it problematic passing the function object since you need to remember to close it afterwards (which you probably won't since you can't see the type)?

Upvotes: 0

Views: 1061

Answers (4)

Burhan Khalid
Burhan Khalid

Reputation: 174624

However, in a dynamic language like python where you can't see the type of the variable, what's the "correct" way to pass a file?

The short answer is - you don't.

In most object oriented languages, there is an object contract which guarantees that if the object has a method quack, it knows how to quack. Some languages are very strict in enforcing this contract (Java, for example) and others not so much.

In the end it comes down to one of Python's principles EAFP:

E asier to a sk for f orgiveness than p ermission. This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements. The technique contrasts with the LBYL style common to many other languages such as C.

LBYL = Look Before You Leap

What this means is that if your method is expecting a "file" (and you state this in your documentation), assume you are being passed a "file like object". Try to execute a file operation on the object (like read() or close()) and then catch the exception if its raised.

One of the main points of the EAFP approach is that you may be getting passed an object that works like a file, in other words - the caller knows what they are doing. So if you spend time checking for exact types, you'll have code that isn't working when it should. Now the burden is on the caller to meet your "object contract"; but what if they are not working with files but with an in-memory buffer (which have the same methods as files)? Or a request object (again, have the same file-like methods). You can't possibly check for all these variations in your code.

This is the preferred approach - instead of the LBYL approach, which would be type checking first.

So, if your method's documentation states that its expecting a file object, it should work with any object that is "file like", but when someone passes it a string to a file path, your method should raise an appropriate exception.

Also, and more importantly - you should avoid closing the object in your method; because it may not be a "file" like explained earlier. However if you absolutely must, make sure the documentation for your method states this very clearly.

Here is an example:

def my_method(fobj):
    ''' Writes to fobj, which is any file-like object,
        and returns the object '''
    try:
        fobj.write('The answer is: {}\n'.format(42))
    except (AttributeError, TypeError):
        raise TypeError('Expected file-like object')
    return fobj

Upvotes: 1

ScottO
ScottO

Reputation: 129

Pass file object just like any other type.

def f(myfile):
    myfile.write('asdf')

ofs = open(filepath, 'w') # ofs is file object
f(ofs) # passes file object
ofs.close()

Can also use closure.

def f():
    return open(filepath, 'w') # returns file object

ofs = f()
ofs.write('something')
ofs.close()

Upvotes: 1

Andrew Chi
Andrew Chi

Reputation: 135

You can use file objects in Python. When they are (automatically) garbage collected, the file will be closed for you.

File objects are implemented using C’s stdio package and can be created with the built-in open() function.

Upvotes: 0

Roger Fan
Roger Fan

Reputation: 5045

Ideally you would be using the with statement whenever you open a file, so closing will be handled by that.

with open('filepath', 'r') as f:
    myfunc(f)

otherstuff() # f is now closed

From the documentation:

It is good practice to use the with keyword when dealing with file objects. This has the advantage that the file is properly closed after its suite finishes, even if an exception is raised on the way.

Upvotes: 2

Related Questions