= Python 2/3 Compatibility = [[TOC]] This guideline documents coding conventions to achieve hybrid Python-2.7/Python-3.5 compatibility in Sahana. It's a working document that will be added to as we move towards full Python-3 compatibility. == Syntax == === No print statements === Don't use the print statement anywhere: {{{#!python print "example" # deprecated }}} You shouldn't use the print-function either, because it can clash with uWSGI: {{{#!python print("example") # not good }}} ...but it can be tolerated in CLI scripts which don't run in the WSGI environment. Best option for debug output is to use sys.stderr.write: {{{#!python import sys sys.stderr.write("example\n") # better }}} ...or the logger (as it can be configured globally to write to a log file instead of the system console): {{{#!python current.log.debug("example") # even better }}} === Use as-syntax for catching exceptions === When catching exceptions in a variable, don't use the comma-syntax: {{{#!python try: ... except Exception, e: # deprecated ... }}} Instead, use the as-keyword: {{{#!python try: ... except Exception as e: # new standard ... }}} == Usage == === No implicit package-relative imports === Python-3 does not search for modules relative to the current module in the same package - unless explicitly indicated by leading {{{.}}} or {{{..}}} in the module path. {{{#!python from s3datetime import s3_format_datetime # inside modules/s3, not working in Python-3 }}} Python-2.7 would search relative to the current module, but on the other hand, it supports the explicit-relative syntax as well. So we decide that only explicit paths shall be used in imports. To import a module in the same package (e.g. within s3), either use explicit-relative syntax: {{{#!python from .s3datetime import s3_format_datetime # inside modules/s3, preferred variant }}} ...or an absolute path relative to modules (or the global python path): {{{#!python from s3.s3datetime import s3_format_datetime # inside modules/s3, acceptable alternative }}} Outside of modules/s3, you should always import from the top-level of the s3 package (because the package structure may change over time): {{{#!python from s3 import s3_format_datetime # outside modules/s3 }}} === Alternative Imports === As the locations and names of some libraries have changed in Python-3, we use the compatibility module ({{{modules/s3compat.py}}}) to implement suitable alternatives. Similarily, the compat module provides alternatives for other objects such as types, functions and certain common patterns. Where an object name is provided by modules/s3compat.py, it '''must''' be imported from there if used. The following objects are provided by s3compat: ||= '''Name''' =||= '''Import''' =||= '''!Comments/Caveats''' =|| ||PY2||{{{from s3compat import PY2}}}||Constant indicating whether we're currently running on Py2, should only be used if alternatives cannot be generalized|| ||StringIO||{{{from s3compat import StringIO}}}|| || ||basestring||{{{from s3compat import basestring}}}|| ||