--- title: Python 2.x Gotchas date: 2023-03-23T23:20:28+00:00 tags: - python identifier: 20230323T232028 --- # Python 2.x Gotchas While at the time of writing (May 2019) the death of Python 2 is just around the corner since I'm working in an enterprise environment I'm sure I will be dealing with Python 2.x code for some time to come. To that end here are some gotchas to keep in mind. ## Missing Features In the 10+ years since Python 3's release it's not surprising that it has accumulated a large list of features that simply don't exist in Python 2.x ### No `enum` module The ``enum`` module was added in Python 3.4. In order to make use of this module in versions of Python older than this we can install the [enum34](https://pypi.org/project/enum34/) package from PyPi ``` pip install enum34 ``` Code that uses the standard ``enum`` module should now work as is. > [!note] > It would seem that this package is not actively maintained with the most recent change being in 2016 at the time of writing. ### No `pathlib` module The ``pathlib`` module was added in Python 3.4. In order to make use of this module in older versions of Python we can install the [pathlib2](https://pypi.org/project/pathlib2) package on PyPi ``` pip install pathlib2 ``` Then code written for the standard ``pathlib`` module should work as expected. ### No `FileNotFoundErrors` Not sure when these were added. If you simply want to be able to throw one it's easy enough to backport one yourself ```python class FileNotFoundError(OSError): pass ``` ## Moved / Changed Features There are a number of features that did exist in Python 2.x but were renamed/moved or tweaked in someway in Python 3.x so that they are not directly compatible with older interpreters anymore ### `configparser` is `ConfigParser` Before Python 3 the ``configparser`` module was called ``ConfigParser``, I'm struggling to see if there are any functional differences between the two versions but there is a actively maintained [configparser](https://pypi.org/project/configparser) package available which has apparently backported a number of changes to older versions of Python ``` pip install configparser ``` In theory code using the standard ``configparser`` module will "just work". ## Best Practice Here is a miscellaneous collection things to do when writing code that will run under Python 2.x that should hopefully minimise the amount of surprises! ### Use new style classes In Python 2.x "new" style classes are an explicit opt-in ```python class MyClass(object): ... ``` ### Define both `__eq__` and `__ne__` When creating a class that you wish to define equality for you need to ensure that you define both the ``__eq__`` and ``__ne__`` special methods for your class to have the behavior you would expect it to. In Python 2.x the default implementation of ``__ne__`` is something like the following. ```python def __ne__(self, other): return not (self is other) ``` For your class to behave as expected you will need to define it as follows ```python class MyClass(object): def __eq__(self, other): ... def __ne__(self, other): return not self.__eq__(other) ``` ### `str != str` In Python 3 the string related datatypes were overhauled to include built-in support for unicode character encodings. This means that the ``str`` type in Python 2.x is **not** equivalent to the ``str`` type in Python 3.x So if you want to check that some value is an instance of the type ``str`` the best way is to make use the ``six`` compatibility package ``` pip install six ``` And to use the following code ```python import six if isinstance(value, six.string_types): ... ```