Migration from OMERO 5.5 (Python 2) to OMERO 5.6 (Python 3)¶
This page serves as a collection of tips the OME team used to get through the migration to Python 3. This is not a complete guide but may serve as a useful starting point.
For more information, please see a dedicated Python 3 page like http://python-future.org/.
Futurize¶
Installing future from Python 3 is now required for all OMERO Python components. This library comes with a tool, futurize which will perform many of the basic transformations needed to migrate Python 2 code to Python 3:
futurize -0 your_file.py
Add -w to update the file in place.
print()¶
The most common transformation needed is adding parentheses around print statements since print is no longer a keyword.
dict.keys()¶
The return value from the keys() method of dictionaries is of type dict_keys and no longer has methods like sort(). Wrap with a call to list if you need the previous behavior: list(my_dict.keys()).
Strings¶
One of if not the major hurdle in upgrading from Python 2 to Python 3 is the shift in strings. In Python 2, there is a separation between str and unicode. In Python 3, both of those are like unicode (but called str) and a new type was introduced: bytes. A good starting places to learn the difference is:
http://python-future.org/compatible_idioms.html?highlight=string#strings-and-bytes
Complicating the matter further is our use of the future library, which tries to help support Python 2 and Python 3 at the same time. Imports including past or future should be looked up in the above guide.
What is str??¶
If nothing special is imported, str is the builtin str in Py2 (non-unicode) but unicode in Py3. String literals like “foo” are also of type str.
If unicode_literal is imported, then “foo” is the same as u”foo” and is unicode in Python 2 or just str in Python 3.
If from builtins import str is imported, then str is more like unicode and may fail existing calls to isinstance().
isinstance(x, str)¶
Since str can change its type, this often will not do what you want. Using past.builtins.basestring is generally a good solution, e.g. isinstance(x, basestring)
str(some_variable)¶
If you are trying to turn a variable into a string, this may not do what you want since it might be creating a unicode.
This is especially problematic for passing strings to Ice methods, which are implemented in C++ and fail spectacularly if they receive non-string objects (like unicode).
future.utils.native_str maintains the previous semantics producing builtin str objects. Native str semantics are especially important when working with Ice, e.g.
ctx = {'omero.group': native_str(groupId)}
conn.getUpdateService().saveArray(pixels, ctx)
StringIO and open(“file”, “r”)¶
StringIO and open() may need replacing with BytesIO and open(“file”, “rb”) respectively. This depends on whether or not your code is expecting a stream to be binary.
Regexes¶
Regexes must start with r”“ for raw to prevent escapes from being misinterpreted (e.g. d).
Numerics¶
long no longer exists. Replace omero.rtypes.wrap(long_value) with omero.rtypes.rlong(long_value).
Division with / now produces a floating point. For example, choice * int(percent) / 100 no longer produces an integer in Python 3. Use //.