My potential qualms about using Python 3 in projects
I wrote recently about why I didn't use the
attrs module recently; the short version is that it would have
forced my co-workers to learn about it in order to work on my code.
Talking about this brings up a potentially awkward issue, namely
Python 3. Just like the
attrs module, working with Python 3 code
involves learning some new things and dealing with some additional
concerns. In light of this, is using Python 3 in code for work
something that's justified?
This issue is relevant to me because I actually have Python 3 code these days. For one program, I had a concrete and useful reason to use Python 3 and doing so has probably had real benefits for our handling of incoming email. But for other code I've simply written it in Python 3 because I'm still kind of enthused about it and everyone (still) does say it's the right thing to do. And there's no chance that we'll be able to forget about Python 2, since almost all of our existing Python code uses Python 2 and isn't going to change.
However, my tentative view is that using Python 3 is a very different
situation than the
attrs module. To put it one way, it's quite
possible to work with Python 3 without noticing. At a superficial
level and for straightforward code, about the only difference between
Python 3 and Python 2 is
print("foo") versus '
Although I've said nasty things about Python 3's automatic string
conversions in the past, they do have the
useful property that things basically just work in a properly formed
UTF-8 environment, and most of the time that's what we have for
(Yes, this isn't robust against nasty input, and some tools are exposed to that. But many of our tools only process configuration files that we've created ourselves, which means that any problems are our own fault.)
Given that you can do a great deal of work on an existing piece of
Python code without caring whether it's Python 2 or Python 3, the
cost of using Python 3 instead of Python 2 is much lower than, for
example, the cost of using the
attrs module. Code that uses
is basically magic if you don't know
attrs; code in Python 3 is
just a tiny bit odd looking and it may blow up somewhat mysteriously
if you do one of two innocent-seeming things.
(The two things are adding a
In situations where using Python 3 allows some clear benefit, such as using a better version of an existing module, I think using Python 3 is pretty easily defensible; the cost is very likely to be low and there is a real gain. In situations where I've just used Python 3 because I thought it was neat and it's the future, well, at least the costs are very low (and I can argue that this code is ready for a hypothetical future where Python 2 isn't supported any more and we want to migrate away from it).
Sidebar: Sometimes the same code works in both Pythons
I wrote my latest Python code as a Python 3
program from the start. Somewhat to my surprise, it runs unmodified
under Python 2.7.12 even though I made no attempt to make it do so.
Some of this is simply luck, because it turns out that I was only
print() with a single argument. In Python 2,
print("fred") is seen as '
print ("fred")', which is just
print "fred"', which works fine. Had I tried to
multiple arguments, things would have exploded.
(I have only single-argument
print()s because I habitually
format my output with
% if I'm printing out multiple things.
There are times when I'll deviate from this, but it's not common.)
Why I didn't use the
attrs module in a recent Python project
I've been hearing buzz about the
attrs Python module for a while (for example). I was recently
writing a Python program where I had some structures and using
attrs to define the classes
involved would have made the code shorter and more obvious. At
first I was all fired up to finally use
attrs, but then I took a
step back and reluctantly decided that doing so would be the wrong
You see, this was code for work, and while my co-workers can work
in Python, they're not Python people in the way that I am. They're
certainly not up on the latest Python things and developments; to
them, Python is a tool and they're happy to let it be if they don't
need to immerse themselves in it. Naturally, they don't know anything
If I used
attrs, the code would be a bit shorter (and it'd be
neat to actually use it), but my co-workers would have to learn at
least something about
attrs before they could understand my code
to diagnose problems, make changes, or otherwise work on it. Using
straightforward structure-style classes is boring, but it's not
that much more code and it's code that's using a familiar, well
established idiom that pretty much everyone is already familiar
Given this situation, I did the responsible thing and decided that
my desire to play around with
attrs was in no way a sufficient
justification for inflicting another Python module to learn on my
co-workers. Boring straightforward code has its advantages.
I can think of two things that would change this calculation. The
first is if I needed more than just simple structure-style classes,
attrs was saving me a significant chunk of code and making
the code that remained much clearer. If I come out clearly ahead
attrs even after adding explanatory comments for my co-workers
(or future me), then
attrs is much more likely to be a win overall
instead of just an indulgence.
(I think that the amount of usage and the size of the codebase matters too, but for us our codebases are small since we're just writing system utility programs and so on in Python.)
The second is if
attrs usage becomes relatively widespread, so that
my co-workers may well be encountering it in other people's Python code
that we have to deal with, in online documentation, and so on. Then
attrs would add relatively little learning overhead and might
even have become the normal idiom. This is part of why I feel much more
free to use modules in the standard library than third-party modules;
the former are, well, 'standard' in at least some sense.
(Mind you, these days I'm sufficiently out of touch with the Python
world that I'm not sure how I'd find out if
attrs was a big, common
thing. Perhaps if Django started using and recommending it.)