0

I want to create a package which should be compatible to Python 2.7 and Python 3.3. The logic should exist only once.

How do you normally represent the programming logic - in Python 2.7 or Python 3.3? Or do you choose a different way?

EDIT: How this issue is handled in the core?

7
  • 1
    Python3 isn't 100% backwards compatible with Python2 so you would have to be very choosy when it comes to what functions to use. Commented May 21, 2013 at 8:16
  • docs.python.org/2/library/2to3.html Commented May 21, 2013 at 8:16
  • 1
    @AshwiniChaudhary 2to3 converts Python 2.x code to Python 3 code that isn't backwards-compatible with Python 2.7. Commented May 21, 2013 at 8:19
  • So, do you recommend coding the package in Python 2.7 and convert it later to Python 3.3? Commented May 21, 2013 at 8:19
  • 6
    See the Porting HOWTO. That document is pretty comprehensive. Commented May 21, 2013 at 8:23

2 Answers 2

2

You do it by quite simply only using those bits of the language that is the same, and by having conditions or exception handling during other parts.

This is harder or easier depending on what your software do, and what versions of Python you need to support. By supporting just Python 2.6, 2.7 and 3.3 it becomes relatively simple.

Exactly how you do it is not answerable in a question on SO, because there is a lot to it.

I recommend you check out this book: http://python3porting.com/ , especially the chapter "Supporting Python 2 and 3 without 2to3 conversion" and the Appendices, that has loads of examples of how to solve most incompatibilities.

The six library may also be useful.

Sign up to request clarification or add additional context in comments.

Comments

2

I tend to use a number of __future__ imports (which are, presumably, safely ignored in Python 3), and the occasionaly try except for some import statements. In addition, I define a stringtype for basestring / str compatibility. Just depending on what I need per module.

For example:

from __future__ import absolute_import
from __future__ import unicode_literals
from __future__ import division
from __future__ import print_function
try:
    import ConfigParser as cfgparser
except ImportError:
    import configparser as cfgparser
try:
    stringtype = basestring
except NameError:
    stringtype = str

I think the six package already does this, so that may be another good option.

4 Comments

Also, from io import open gives you strictly the Python 3 open builtin (with, among other things, its platform-independent meaning of binary vs text files).
This is just a small sample of the things you need to do. I don't think it as such is a very useful answer.
@lennart I agree that it's not complete. It's just what I need to use, and mostly on a per-module basis (thus, the ConfigParser import isn't always there). It serves more as an example than as a complete answer, which I thought may be useful to get someone started. For a more complete answer, the porting howto Martijn has pointed out does contain most of that info (it mentions six as well).
I would advise against using the unicode_literals future module mainly because of the regressions with other modules/3rd-party libs I've encountered as stated in the futures doc. Its a lot of trouble to fix. A more cautious approach, such as using the u'' prefix is preferable. I upvoted because of the boilerplate.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.