Package: py27hash
py27hash: Python 2.7 hashing and iteration in Python 3+This package helps ease the migration from Python 2 to 3 for applications that depend on the old hash/iteration order of sets/dicts. Even when setting PYTHONHASHSEED=0, the hash (and default iteration order) will still be different as the hashing algorithm changed in Python 3. This package allows Python 2.7 hashing and set/dict iteration.InstallationThe easiest way to install is via pip and PyPIpip install py27hashYou can also use Git to clone the repository from GitHub and install it manually:git clone https://github.com/neuml/py27hash.git
cd py27hash
pip install .Python 2.7 and 3+ are supported.How to useYou only need to replace object instantiation to use this package. There are multiple ways to do this, with the best way to do it on a case by case basis.Replace each instantiationThe first example replaces a single dict and set with a 2.7 dict.frompy27hash.dictimportDict# Replace {} with Dict()d=Dict()d["a"]=1# Python 2.7 sets can be used in the same manner.frompy27hash.setimportSet# Replace set() with Set()d=Set()d.add("a")Override function via importThe same example above can be changed to override the dict and set import statement. This will globally change an entire file which could cause issues but it is an option. If a dict or set was created with the {} syntax, it still needs to be changed to dict()/set().frompy27hash.dictimportDictasdictd=dict()d["a"]=1# Python 2.7 sets can be used in the same manner.frompy27hash.setimportSetassetd=set()d.add("a")Using other methodsThe hashing and key iteration methods can be directly accessed via the hash and key packages as follows.frompy27hash.hashimporthash27print(hash27("test1234"))# As with the example above you could even override the hash function for a particular file.fromp27hash.hashimporthash27ashashprint(hash("test1234"))Both Dict and Set are backed by the keys class. As new values as added/modified, a Keys instance tracks each value to store the order via Python 2.7 hashing. This class can also be used directly.fromp27hash.keyimportKeyskeys=Keys()keys.add("1")keys.add("2")BackgroundPython 2 will reach end of life (EOL) on January 1st, 2020. This package helps ease the migration from Python 2 to 3 for applications that depend on the old hash/iteration order of sets/dicts. Even when setting PYTHONHASHSEED=0, the hash (and default iteration order) will still be different as the hashing algorithm changed in Python3. Python 3.6 changed the default iteration order to insertion order.One target use case is with machine learning. Optimization of machine learning model hyperparameters can take a very long time and if a model was built under Python 2 and feature set/dicts used the default sort order, new parameters would need to be used. This library can be used to allow a full conversion to Python 3 while fixes are made to re-optimize large model parameters. There likely are other use cases, especially in the scientific/engineering space where non-random deterministic iteration in Python 2 was used to create reproducible results.This package implements logic in cpython 2.7 C source, mainly the Objects/ folder in pure Python. Performance was not a goal of this package and it will perform worse than native collections. It should only be used when there is a clear use case to preserve Python 2.7 hashing/iteration to ease a transition to Python 3.DevelopmentIf an issue is found in this library, it can be cloned and changed.git clone https://github.com/neuml/py27hash.git
cd py27hashAfter changes are made to the source, unit tests should also be added and run via:
scripts/test.shDuring development slower tests can be skipped via:
scripts/test.sh skipslow