Check if variable is an instance of a File object

S

sc_wizard29

Hi everyone,

Maybe these questions will sound strange to you, but I sometime have a
hard time switching from Java to Python ;-)

Let's say I have a function like this :

def show_lines(file):
for next_line in file:
...

What can I do to be sure that the input argument is indeed a 'File'
object ?

#1 : should I start by checking that 'file' is indeed an instance of a
File object ? (and how do I do this ?)
#2 : should I do nothing ? (but I don't like the idea of risking to
have a runtime exception raised somewhere)

Thanks for helping...
 
C

Calvin Spealman

Hi everyone,

Maybe these questions will sound strange to you, but I sometime have a
hard time switching from Java to Python ;-)

Let's say I have a function like this :

def show_lines(file):
for next_line in file:
...

What can I do to be sure that the input argument is indeed a 'File'
object ?

#1 : should I start by checking that 'file' is indeed an instance of a
File object ? (and how do I do this ?)
#2 : should I do nothing ? (but I don't like the idea of risking to
have a runtime exception raised somewhere)

Thanks for helping...

Do nothing!

The caller might pass you a file-like object, and you can never be
exactly sure. Duck typing rules in this case. If what they pass acts
like a file, then it must be a file (for as much as the function needs
to care, anyway). Don't want to risk an exception at runtime? Well,
isn't that what you would do if you explicitly checked for a file
object and had something else, anyway? Just assume its a file and if
there is an error it should propogate because one of the callers
messed up and should know that.
 
M

Marc 'BlackJack' Rintsch

sc_wizard29 said:
Maybe these questions will sound strange to you, but I sometime have a
hard time switching from Java to Python ;-)

Let's say I have a function like this :

def show_lines(file):
for next_line in file:
...

What can I do to be sure that the input argument is indeed a 'File'
object ?

Why do you want to be sure? I would even rename the argument:

def show_lines(lines):
for line in lines:
...

This works with *every* iterable that contains "lines". No need to
"cripple" it with a type checking.
#2 : should I do nothing ? (but I don't like the idea of risking to
have a runtime exception raised somewhere)

Then don't use Python. Except `SyntaxError` almost every
exception is a runtime one.

And what do you do if you check for `file` and it isn't such an instance?
Raise an exception? A no, that's something you don't like. So what else? ;-)

Ciao,
Marc 'BlackJack' Rintsch
 
S

sc_wizard29

Marc 'BlackJack' Rintsch a ecrit :
And what do you do if you check for `file` and it isn't such an instance?
Raise an exception? A no, that's something you don't like. So what else? ;-)

Well, I prefer the idea of raising my *own* exception to the idea of
having an unknown behavior occur (for ex : what if the argument is NOT
a File, but is "itereable" ?)

But anyway, I guess the most "pythonic" way is to do nothing ;-)


One more question : how to test if 'file' is a File object ?
 
P

Peter Otten

Marc 'BlackJack' Rintsch a ecrit :


Well, I prefer the idea of raising my *own* exception to the idea of
having an unknown behavior occur (for ex : what if the argument is NOT
a File, but is "itereable" ?)

But anyway, I guess the most "pythonic" way is to do nothing ;-)

Indeed, don't waste time to make your code less general. Why would you want
to prevent your show_lines() function from processing a list of strings or
a StringIO?
One more question : how to test if 'file' is a File object ?

The file type is actually spelt lowercase, so 'file' is not a good idea as a
variable name.
True

isinstance() returns True for subclasses, if you don't want that either:
True

Peter
 
B

Bruno Desthuilliers

Hi everyone,

Maybe these questions will sound strange to you, but I sometime have a
hard time switching from Java to Python ;-)

Let's say I have a function like this :

def show_lines(file):
for next_line in file:
...

OT : this will shadow the builtin file type. Avoid shadowing builtin
types if you value your mental sanity !-)
What can I do to be sure that the input argument is indeed a 'File'
object ?

Why do you think you need "to be sure that the input argument is indeed
a 'File' object" ? As long as the object passed in is able to answer to
the messages you'll send to it, everything's fine, isn't it ? And if it
fails, well, you'll find out pretty soon...
#1 : should I start by checking that 'file' is indeed an instance of a
File object ?

Unless you have a *very* compelling reason to do so (and I can't imagine
one here), definitively, no. FWIW, it's pretty common in Python to pass
file-like objects (StringIo comes to mind... but there are lots of other
cases) to functions expecting a file object. And remember that Python
doesn't relies on inheritence for typing. Also, for what you showed of
your code, any iterable seems ok !-)
(and how do I do this ?)

isinstance(obj, *classes)

OT : note that in your case, since the arg name 'file' shadows the
builtin type, you'll have hard time using it !-)
#2 : should I do nothing ?

Yes. Well, IMHO.
(but I don't like the idea of risking to
have a runtime exception raised somewhere)

Err... What exactly do you intend to do if the object passed in is not a
file ? Raise a TypeError ? If so, when do you think it will fires ? Yes
my friend- at runtime !-)

As you noticed, switching from Java to Python requires some mental
adjustements... Not fearing runtime exceptions is one of them. Thinking
in terms of implied interface is another one. In your above code, you
really don't care if the objects is a file or not - you just care if the
object support the subset of the file interface you intend to use. And
this, you'll only know at runtime.
 
B

Bruno Desthuilliers

Marc 'BlackJack' Rintsch a ecrit :


Well, I prefer the idea of raising my *own* exception to the idea of
having an unknown behavior occur

The behavior in case of an uncaught exception is pretty well defined :
your app crashes with an error message and a traceback. Note that
nothing prevents you to try and catch most execptions at the top-level
and do whatever seems appropriate here (log the error, try to see if the
app just display the error and continue with another task or if it's
time to suicide, etc)...
(for ex : what if the argument is NOT
a File, but is "itereable" ?)

hard to tell without knowing the rest of the code, but if it's something
like this :

def show_lines(fileobj):
for line in fileobj:
print line

it will just work...
 
F

Fuzzyman

Hi everyone,

Maybe these questions will sound strange to you, but I sometime have a
hard time switching from Java to Python ;-)

Let's say I have a function like this :

def show_lines(file):
for next_line in file:
...

What can I do to be sure that the input argument is indeed a 'File'
object ?

#1 : should I start by checking that 'file' is indeed an instance of a
File object ? (and how do I do this ?)
#2 : should I do nothing ? (but I don't like the idea of risking to
have a runtime exception raised somewhere)

It depends how you want to do your exception handling. Assuming you
have passed in an object that isn't a file, how do you want to handle
it ?

Here is an example :

class ProgrammerError(Exception): pass

def function(myFile):
if not isinstance(myFile, file):
raise ProgrammerError
for line in myFile:
print myFile

try:
function('something')
except ProgrammerError:
print 'I did something wrong'

Writing tests that check your code doesn't do this would be a better
approach. This is 'strong testing' as opposed to 'strong typing'.

Fuzzyman
http://www.voidspace.org.uk/python/index.shtml
 
G

George Sakkis

Bruno said:
Unless you have a *very* compelling reason to do so (and I can't imagine
one here), definitively, no. FWIW, it's pretty common in Python to pass
file-like objects (StringIo comes to mind... but there are lots of other
cases) to functions expecting a file object. And remember that Python
doesn't relies on inheritence for typing. Also, for what you showed of
your code, any iterable seems ok !-)

Well, not quite; string comes to mind as a common counter example.
Still, a usually better way to handle a string argument than raising an
exception is wrap it in StringIO:

from cStringIO import StringIO

def show_lines(text):
if isinstance(text,basestring):
text = StringIO(text)
for line in text:
# do something


George
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top