Python-2to3: Safe Set of Fixers for Python 2 and 3
Asked Answered
F

2

2

What subset of Python 2to3 fixers output valid Python 2 code?

Rather than move to Python 3 all at once, I'd like to use 2to3 to get most of the way there, saving the really hairy stuff (e.g., unicode changes) for a later time or possibly using six to support both. I'd like an initial pass to be done by 2to3, but I want it to generate valid Python 2 code as an intermediate step.

Note: I'm aware of a similar question, but it wasn't really answered.

Flatiron answered 15/5, 2019 at 21:28 Comment(0)
M
1

I recently found a tool futurize that does this for you. In EPEL there's even an RPM for CentOS 6 (which I am stuck with on some machines at work) - it's python-future.

http://python-future.org/automatic_conversion.html - stage 1 is the "prep for python 3 while maintaining compatibility" with stock packages. I've found that stage 2 requires other packages that are installed with it, but not available on other machines when I copy the scripts around.

One example: futurize -l -f all -f idioms -f ws_comma -x long *py

Adding -w will write the changes back out for you.

Molotov answered 13/11, 2019 at 1:35 Comment(0)
B
-1

I don't think you're going to find one. Your best approach instead is to use the #! syntax to indicate what Python you want to use and use 2to3 as you're ready on each one. (If you're on Windows, look into Python launcher to make coexistence a little easier.)

I have one module I wrote that needs to work with both 2 and 3; and I have code at the top that looks like this:

import sys
PYTHON3 = sys.version_info.major == 3
PYTHON2 = sys.version_info.major == 2

if PYTHON2:
    import StringIO
    stringio = StringIO.StringIO
    bytesio = StringIO.StringIO # In Python2, stringIO takes strings of binary data
    import urllib2
    URL_open = urllib2.urlopen
    HTTPError = urllib2.HTTPError

if PYTHON3:
    import io
    stringio = io.StringIO
    bytesio  = io.BytesIO # In Python3, use BytesIO for binary data
    import urllib.request
    URL_open = urllib.request.urlopen
    import urllib.error
    HTTPError = urllib.error.HTTPError

and scattered throughout things like:

if PYTHON2:
    f = stringio(self.XMLData)
if PYTHON3:
    f = bytesio(self.XMLData.encode(encoding="utf-8"))

It's not like there's way of expressing a line that will work in both systems. You need a lot of patching like this. It's really not worth it unless you have a use case (like this) where there's some reason you must support both Python2 and Python3 in one module.

My use case was relatively straightforward. The similar question you refer to points to the Dive Into Python "Porting Code to Python 3 with 2to3" chapter, which shows how much stuff is different, much of which is incompatibly different, requiring a lot of conditional coding as above. I wouldn't recommend it.

Bellay answered 16/5, 2019 at 3:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.