Best Practice: Python 3 Migration

One of the major changes in UCS 5 is Python 3 compatibility. While most UCS components are adjusted automatically, manually crafted Python code, for example in UCR templates or hooks, has to be adapted by hand.
This article shall serve as a collection of useful resources and helpful tips concerning the Python 3 migration.

Check for compatibility

While updating to UCS 5 templates are checked automatically via the pre-update check python_ucr_template_compatibility which is documented here:
https://docs.software-univention.de/release-notes-5.0-0-en.html#relnotes:prepare

Not all templates are needed anymore, files save to remove are documented in the article UCS 5.0 upgrade failed: solve pre-update check python-ucr-template-compatibility

Manually this check can be run via the py_compile module:

python3 -m py_compile file_to_check.py

Migrating

Generally speaking there are many guides and recommendations on how to make code Python 3 compatible.

For an overview of key differences this article is useful:

Convert Python2 to Python3 and check the results:

apt install 2to3
2to3 -w file_to_migrate.py
git diff

Specifically targeted at UCS our developer reference has it’s own chapters for UDM, UCR and listener related changes:

UDM

https://docs.software-univention.de/developer-reference-5.0.html#udm:python-migration

UCR

https://docs.software-univention.de/developer-reference-5.0.html#ucr:python-migration

Listener

https://docs.software-univention.de/developer-reference-5.0.html#listener:python-migration

Known errors

Some well known errors typically happen in context of Python 2/3 changes and will be listed here.

TypeError: a bytes-like object is required, not ‘str’

Python 3 strings are by default unicode whereas Python 2 strings are stored as bytes. To convert between those, strings can be prefixed with u or b like so: u"unicoded string" vs. b'bytestring'.
This error can happen in various contexts, so there is no one-for-all fix. Typically one can check for files opened with a wrong mode or encoding or string parameters to methods/functions.

SyntaxError: Missing parentheses in call to ‘print’. Did you mean print(test)?

In Python 2 print was a statement, in Python 3 printing is done via the print() function. To fix this parentheses have to encompass the output to be printed.

SyntaxError: except Exception, e

If the catched exception should be accessible is has to be assigned with except Exception as e: instead of except Exception, e:.

Syntax Error: Invalid Syntax

In Python 3 the Return Type of map() changed to a <map Object>. In Python 2 it was a List.
→ QuickFix: use a list comprehension like [foo(x) for x in bar]

2 Likes
Mastodon