Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > isinstance(.., file) for Python 3

Reply
Thread Tools

isinstance(.., file) for Python 3

 
 
Ulrich Eckhardt
Guest
Posts: n/a
 
      11-08-2012
Hi!

I have two problems that are related and that I'd like to solve together.

Firstly, I have code that allows either a file or a string representing
its content as parameter. If the parameter is a file, the content is
read from the file. In Python 2, I used "isinstance(p, file)" to
determine whether the parameter p is a file. In Python 3, the
returnvalue of open() is of type _io.TextIOWrapper, while the built-in
class file doesn't exist, so I can't use that code.

Secondly, checking for the type is kind-of ugly, because it means that I
can't use an object that fits but that doesn't have the right type. In
other words, it breaks duck-typing. This is already broken in the Python
2 code, but since I have to touch the code anyway, I might as well fix
it on the way.

If possible, I'm looking for a solution that works for Pythons 2 and 3,
since I'm not fully through the conversion yet and have clients that
might use the older snake for some time before shedding their skin.

Suggestions?

Uli


 
Reply With Quote
 
 
 
 
MRAB
Guest
Posts: n/a
 
      11-08-2012
On 2012-11-08 12:05, Ulrich Eckhardt wrote:
> Hi!
>
> I have two problems that are related and that I'd like to solve together.
>
> Firstly, I have code that allows either a file or a string representing
> its content as parameter. If the parameter is a file, the content is
> read from the file. In Python 2, I used "isinstance(p, file)" to
> determine whether the parameter p is a file. In Python 3, the
> returnvalue of open() is of type _io.TextIOWrapper, while the built-in
> class file doesn't exist, so I can't use that code.
>
> Secondly, checking for the type is kind-of ugly, because it means that I
> can't use an object that fits but that doesn't have the right type. In
> other words, it breaks duck-typing. This is already broken in the Python
> 2 code, but since I have to touch the code anyway, I might as well fix
> it on the way.
>
> If possible, I'm looking for a solution that works for Pythons 2 and 3,
> since I'm not fully through the conversion yet and have clients that
> might use the older snake for some time before shedding their skin.
>
> Suggestions?
>

Instead of checking whether it's a file, check whether it's a string!
 
Reply With Quote
 
 
 
 
Steven D'Aprano
Guest
Posts: n/a
 
      11-08-2012
On Thu, 08 Nov 2012 13:05:22 +0100, Ulrich Eckhardt wrote:

> Firstly, I have code that allows either a file or a string representing
> its content as parameter. If the parameter is a file, the content is
> read from the file. In Python 2, I used "isinstance(p, file)" to
> determine whether the parameter p is a file. In Python 3, the
> returnvalue of open() is of type _io.TextIOWrapper,


Incorrect.

py> type(open('x', 'wb'))
<class '_io.BufferedWriter'>

The type returned by open will depend on what you open and how you open
it.

> while the built-in
> class file doesn't exist, so I can't use that code.


import io
file = io._IOBase

will probably work. But consider it a little smelly, since you're relying
on an implementation detail.


> Secondly, checking for the type is kind-of ugly, because it means that I
> can't use an object that fits but that doesn't have the right type. In
> other words, it breaks duck-typing. This is already broken in the Python
> 2 code, but since I have to touch the code anyway, I might as well fix
> it on the way.


if hasattr(obj, 'read'):
# object is file-like enough to treat as a file
pass

That means that you can also use io.StringIO objects as pseudo-files too.



--
Steven
 
Reply With Quote
 
Chris Angelico
Guest
Posts: n/a
 
      11-08-2012
On Thu, Nov 8, 2012 at 11:05 PM, Ulrich Eckhardt
<(E-Mail Removed)> wrote:
> Firstly, I have code that allows either a file or a string representing its
> content as parameter. If the parameter is a file, the content is read from
> the file. In Python 2, I used "isinstance(p, file)" to determine whether the
> parameter p is a file...


Can you use the inverted check "isinstance(p, str)"? It's more likely
that you'll want to pass a file-like object than a string-like object.
This would work on Python 2 as well, though it's semantically
different; to safely check for both Unicode and bytes strings on both
Py2 and Py3, this may work:

# Once-off:
try:
basestring
except NameError:
basestring = (str, bytes)

# Is p a string?
if isinstance(p, basestring):
pass

It abuses the fact that isinstance will happily accept the
'basestring' common supertype of both strings in Python 2, but will
equally happily accept a tuple of types.

ChrisA
 
Reply With Quote
 
Peter Otten
Guest
Posts: n/a
 
      11-08-2012
Ulrich Eckhardt wrote:

> Hi!
>
> I have two problems that are related and that I'd like to solve together.
>
> Firstly, I have code that allows either a file or a string representing
> its content as parameter. If the parameter is a file, the content is
> read from the file. In Python 2, I used "isinstance(p, file)" to
> determine whether the parameter p is a file. In Python 3, the
> returnvalue of open() is of type _io.TextIOWrapper, while the built-in
> class file doesn't exist, so I can't use that code.
>
> Secondly, checking for the type is kind-of ugly, because it means that I
> can't use an object that fits but that doesn't have the right type. In
> other words, it breaks duck-typing. This is already broken in the Python
> 2 code, but since I have to touch the code anyway, I might as well fix
> it on the way.
>
> If possible, I'm looking for a solution that works for Pythons 2 and 3,
> since I'm not fully through the conversion yet and have clients that
> might use the older snake for some time before shedding their skin.
>
> Suggestions?


In order of obviousness:
hasattr(p, "read")
not isinstance(p, str)
iter(p) is p

Or you change the interface

def f(*, contents=None, file=None):
if contents is None:
with open(file) as f:
contents = f.read()
... # work with contents



 
Reply With Quote
 
Stefan Behnel
Guest
Posts: n/a
 
      11-08-2012
Duncan Booth, 08.11.2012 14:58:
> Ulrich Eckhardt wrote:
>> If possible, I'm looking for a solution that works for Pythons 2 and 3,
>> since I'm not fully through the conversion yet and have clients that
>> might use the older snake for some time before shedding their skin.
>>
>> Suggestions?

>
> Why bother checking types at all?
>
> def foo(file_or_string):
> try:
> data = file_or_string.read()
> except AttributeError:
> data = file_or_string
> ... use data ...


Or, a tiny bit more safely:

try:
read = file_or_string.read
except AttributeError:
data = file_or_string
else:
data = read()

I'd rather go with one of the previous solutions, though.

Stefan


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: [Python-Dev] [python-committers] [RELEASED] Python 3.2 rc 1 R. David Murray Python 0 01-17-2011 02:23 PM
Re: [Python-Dev] [python-committers] [RELEASED] Python 3.2 rc 1 Senthil Kumaran Python 0 01-17-2011 10:31 AM
Re: [Python-Dev] [Python-3000] RELEASED Python 2.6a1 and 3.0a3 Martin v. L÷wis Python 0 03-01-2008 10:51 PM
Re: [Python-Dev] [Python-3000] RELEASED Python 2.6a1 and 3.0a3 Paul Moore Python 0 03-01-2008 10:39 PM
Searching comp.lang.python/python-list@python.org (was: UTF-8) skip@pobox.com Python 0 03-10-2007 02:50 PM



Advertisments