# Import “izip” for different versions of Python

A common idiom that I use for Python2-Python3 compatibility is:

try:
from itertools import izip
except ImportError:  #python3.x
izip = zip


However, a comment on one of my Stack Overflow answers implies that there may be a better way. Is there a more clean way to accomplish this?

• Perhaps the commenter meant to use the import to shadow zip? I.e., try: from itertools import izip as zip; except ImportError: pass. (Please excuse the lack of newlines.) – jpmc26 May 16 '13 at 23:10
• Perhaps -- (I knew about that one). I was just wondering if there was some magic with __import__ that I didn't know about or something. – mgilson May 16 '13 at 23:14

Not sure this is really an answer, or I should elaborate on my comment, and in hindsight probably not even a very good comment anyway, but:

Firstly, you can just simplify it to:

try:
from itertools import izip as zip
except ImportError: # will be 3.x series
pass


What I was thinking about was:

From 2.6 you can use as per the docs:

from future_builtins import map # or zip or filter


You do however then have the same problem of ImportError - so:

try:
from future_builtins import zip
except ImportError: # not 2.6+ or is 3.x
try:
from itertools import izip as zip # < 2.5 or 3.x
except ImportError:
pass


The advantage of using future_builtin is that it's in effect a bit more "explicit" as to intended behaviour of the module, supported by the language syntax, and possibly recognised by tools. For instance, I'm not 100% sure, but believe that the 2to3 tool will re-write zip correctly as list(zip(... in this case, while a plain zip = izip may not be... But that's something that needs looking in to.

Updated - also in the docs:

The 2to3 tool that ports Python 2 code to Python 3 will recognize this usage and leave the new builtins alone.

• Ahh ... I didn't actually know about future_builtins. It seems a little silly that they don't have that in python3 though. I don't know why they didn't do something like from __future__ import zip instead. That would have made sense to me. Anyway, thanks for the explanation. – mgilson May 17 '13 at 1:16
• I also think it's silly that 2to3 recognizes the usage of future_builtins yet leaves the from future_builtins import whatever statement(s) in the output. – martineau Jun 25 '13 at 19:19

If you are trying to make Python 2.x code compatible with Python 3.x you should look at six:

http://pythonhosted.org/six/#module-six.moves

• Yeah, six is nice. Generally, if it's simple enough though, I tend to prefer to avoid the extra dependency. – mgilson May 20 '13 at 23:50

This is roughly twice as fast as using a try/except:

import itertools
zip = getattr(itertools, 'izip', zip)

• I find this claim hard to believe ... getattr works by catching the AttributeError and substituting the default value. Admittedly, that's implemented in C so it might be slightly faster, but I find it hard to believe that there's a factor of 2. I also find it hard to believe that the time would matter in the real world if you have this at the top-level of your module... Finally, this is possibly the cleanest way to write it that I've seen. Kudos for that :-). – mgilson Jun 21 '17 at 3:28
• @mgilson: Use timeit and test it yourself. I thought it might be faster, but I didn't think ~2x. – Mike McKerns Jun 22 '17 at 11:38