Python 2 to 3

From raju

dummy

str __iter__ attrbute

python 2 python 3
>>> hasattr('20201210', '__iter__')
False
>>> hasattr('20201210', '__iter__')
True
tested using 2.7.15 3.8.1

To migrate the code from Python 2 to 3, change

    if hasattr(x, '__iter__'):
    

to

    if hasattr(x, '__iter__') and not isinstance(x, str):
    

Similarly change

    if not hasattr(x, '__iter__'):
    

to

    if not hasattr(x, '__iter__') or isinstance(x, str):
    

Testing:

python 2 python 3
>>> import pandas as pd
>>> a = ['foo', 5, pd.Series()]
>>> [True if hasattr(x, '__iter__') else False for x in a]
[False, False, True]

>>> [True if hasattr(x, '__iter__') and not isinstance(x, str) else False for x in a]
[False, False, True]
>>> [True if not hasattr(x, '__iter__') or isinstance(x, str) else False for x in a]
[True, True, False]
>>> import pandas as pd
>>> a = ['foo', 5, pd.Series()]
>>> [True if hasattr(x, '__iter__') else False for x in a]
[True, False, True]

>>> [True if hasattr(x, '__iter__') and not isinstance(x, str) else False for x in a]
[False, False, True]
>>> [True if not hasattr(x, '__iter__') or isinstance(x, str) else False for x in a]
[True, True, False]
tested using 2.7.15 3.8.1

Note: The elements of the test data are chosen to cover the following cases - a string object, a non string object with no __iter__ attribute, a non string object with an __iter__ attribute.

Ref:- https://stackoverflow.com/a/10509817/6305733

import statements

Python 3 does not allow implicit relative imports. They were allowed in python 2.

python 2 python 3
import foo from . import foo
from bar import foo from .bar import foo

Ref:-

tags | python3 does not look in current directory for modules, python 3 import local module

SyntaxWarning: "is" with a literal. Did you mean "=="?

python 2 python 3
issue
>>> 1 is 1
True
>>> 'a' is 'a'
True
>>> 1 is 1
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True
>>> 'a' is 'a'
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True
fix
>>> 1 == 1
True
>>> 'a' == 'a'
True
tested using 2.7.15 3.8.1

SafeConfigParser DeprecationWarning

python 2 python 3
issue
>>> import configparser
>>> a = configparser.SafeConfigParser()
>>> import configparser
>>> a = configparser.SafeConfigParser()
<stdin>:1: DeprecationWarning: The SafeConfigParser class has been renamed
to ConfigParser in Python 3.2. This alias will be removed in future versions.
Use ConfigParser directly instead.
fix
>>> a = configparser.ConfigParser()
tested using 2.7.15 3.8.1

comparing None and a string

python 2 python 3
issue comparison of None and a string is allowed. not allowed.
example
>>> None < 'a'
True
>>> None < ''
True
>>> None < 'a'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'NoneType' and 'str'
>>> None < ''
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'NoneType' and 'str'
tested using 2.7.15 3.8.1

Ref:-

tags | python 3 comparison operators using None

To find out | Is None considered less than any string in Python 2?

replace map calls with none as first argument

tags | map with None as function, 2 to 3 starred expression

In Python 2:

    $ ipython
    Python 2.7.13 |Anaconda custom (64-bit)| (default, Dec 19 2016, 13:29:36) [MSC v.1500 64 bit (AMD64)]
    
    In [1]: a = [1,2,3]; b = [4,5]; c = [6]
       ...: for i,j,k in map(None, a, b, c):
       ...:     print i, 'blah', j, 'blah', k
    1 blah 4 blah 6
    2 blah 5 blah None
    3 blah None blah None
    
    In [2]: import itertools
       ...: for i,j,k in itertools.izip_longest(a,b,c):
       ...:     print i, 'blah', j, 'blah', k
    1 blah 4 blah 6
    2 blah 5 blah None
    3 blah None blah None
    

In Python 3:

    $ ipython
    Python 3.6.8 |Anaconda custom (64-bit)| (default, Dec 30 2018, 18:50:55) [MSC v.1915 64 bit (AMD64)]
    
    In [1]: import itertools
       ...: a = [1,2,3]; b = [4,5]; c = [6]
       ...: for i,j,k in itertools.zip_longest(a,b,c):
       ...:     print(i, 'blah', j, 'blah', k)
    1 blah 4 blah 6
    2 blah 5 blah None
    3 blah None blah None
    

Ref:- https://stackoverflow.com/questions/1277278/python-zip-like-function-that-pads-to-longest-length

None value comparison

In python 2, comparing two values using a < b is allowed even if both values are None. But Python 3 will throw an exception on it.

In Python 2

    $ python
    Python 2.7.15 |Anaconda, Inc.| (default, May  1 2018, 18:37:09) [MSC v.1500 64 bit (AMD64)] on win32
    >>> a = None; b = None; c = 2
    
    >>> a == b
    True
    >>> a != b
    False
    >>> a < b
    False
    >>> a > b
    False
    
    >>> a == c
    False
    >>> a != c
    True
    >>> a < c
    True
    >>> a > c
    False
    

In Python 3

    $ python
    Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)] on win32
    >>> a = None; b = None; c = 2
    
    >>> a == b
    True
    >>> a != b
    False
    >>> a < b
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: '<' not supported between instances of 'NoneType' and 'NoneType'
    >>> a > b
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: '>' not supported between instances of 'NoneType' and 'NoneType'
    
    >>> a == c
    False
    >>> a != c
    True
    >>> a < c
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: '<' not supported between instances of 'NoneType' and 'int'
    >>> a > c
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: '>' not supported between instances of 'NoneType' and 'int'
    

See also:- https://stackoverflow.com/questions/8961005/comparing-none-with-built-in-types-using-arithmetic-operators


integer division

python 2 python 3
issue
>>> 17 / 3
5
>>> 17 / 3
5.666666666666667
fix
>>> 17 // 3
5
>>> 17 // 3
5
tested using 2.7.15 3.8.1

Ref:- https://stackoverflow.com/a/21317017/6305733

useful links