isinstance(.., file) for Python 3
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: isinstance(.., file) for Python 3
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! -- http://mail.python.org/mailman/listinfo/python-list
Re: isinstance(.., file) for Python 3
On Thu, Nov 8, 2012 at 11:05 PM, Ulrich Eckhardt ulrich.eckha...@dominolaser.com 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: isinstance(.., file) for Python 3
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: isinstance(.., file) for Python 3
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: isinstance(.., file) for Python 3
Ulrich Eckhardt ulrich.eckha...@dominolaser.com 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 ... -- Duncan Booth http://kupuguy.blogspot.com -- http://mail.python.org/mailman/listinfo/python-list
Re: isinstance(.., file) for Python 3
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 -- http://mail.python.org/mailman/listinfo/python-list