Hacker News new | ask | show | jobs
by plesner 4088 days ago
Making python 3 more attractive is not the solution, it's part of the problem.

I can't use just python 3 because python 2 is still widely used. I can write code that works on both but now I'm using the worst of both worlds, and even worse I now have to test on both. And that'll last until python 2 goes away completely which, - when has a language ever gone away quickly?

These aren't fun problems. Improving python 3, making it more attractive, that's fun. But that's problem 2. Making migration less painful for me should be problem 1. Who's working actively on that?

What particularly grinds my gears is the apparent disregard for migration in the design. Take the changes to the print statement. Often this is the only thing that prevents my existing code from working in python 3. And it's in my muscle memory so I always get snagged when debugging on python 3. For what? Take a read through the rationale: https://www.python.org/dev/peps/pep-3105/#rationale. Most of the benefits you could have had if you'd named the new print function something else. I can understand that you regret adding it in the first place. What's even worse though? Adding it and then removing it in an incompatible way.

If you want to make python 3 more attractive maybe make migration easier before going on to the fun improvements? There are low-hanging fruits for migration too. How about adding back the print statement?

9 comments

Migration is a critical issue for python 3 adoption. I think python 3 should have done something similar to Protocol Buffers v3 (proto3) by introducing syntax = "python3" statement and let runtime support both v2 and v3. This allows people migrate one file at a time. In any large scale production environment, this is pretty much the only practical way for migration.

Another critical mistake python 3 made was unicode support. For people who work deeply in i18n support, UTF-8 encoding is the only practical solution. Python 3 string should use UTF-8 much like Go. Just for reference, Google stores almost all data as protobuf, which only support UTF-8. That proves the story.

A runtime that can support both v2 and v3 files is a nice idea and has been proposed before, but is virtually impossible because of the unicode changes.

I don't understand where you see the mistake in Python 3 with unicode. What encoding Python internally uses to store strings doesn't really matter. What's important is that it is always known what encoding is used. This was unclear in Python 2 and Python 3 fixed this.

Nowadays, most of text data are stored in UTF-8 format. If the language uses UTF-8 as native string format, it is much easier for text processing, which is why Go chose it. There are a lot of subtle technical details you will only realize after working with many text processing components.
Can't agree more.
`print` statement is not a big deal for me. But one thing that especially annoys me is the functions in the module `itertools`. In Python 2, I use `itertools.izip` or `itertools.imap` a lot, because I'd like to avoid creating a large list only to iterate over once. When I tried migrating to Python 3, I found out that these functions are gone, and I was supposed to use plain `zip` and `map` instead. I was furious. How easy it is to let `itertools` contain these functions as aliases to the builtin? And I felt that I was punished for writing efficient code, while people who code carelessly get rewarded. I switched back instantly.
Doesn't 2to3 handle all of these problems?
2to3 will write you a patch so you can port the code to py3 if that's what you want, but if you then also want to maintain py2 compatibility you've got more work to do.

I can't speak to the wisdom of making map and zip builtins, but that's what they are in py3, and the six module will make using them that way automatically backward and forward compatible:

    from six import map, zip
Map and zip were builtins in 2.x as well, just not the itertools.imap/itertools.izip variants.
It is not the difficulty of handling these situations. It is the lack of regard for Python users like me. Again, as I have said, I feel punished for milking the most from the language, whereas those who code carelessly are rewarded with performance improvement and no pains in transition. Why should I switch to a language that punishes me for good behavior?

It is the same as the `u` prefix. Those who actually cared to get Unicode right got punished when Python 3.0 came out because now none of their code compiled, whereas those who just assume everything is ASCII went on without problems.

Removing the print statement is, to me, an extremely frustrating breaking change to make.

If nothing else, I feel that backward compatibility should be given toward's a language's canonical "hello world" example.

It can't be that difficult to do a one-off `find . -type f -name '*.py' -print0 | xargs -0 grep 'print '`, change the print statements to functions and add `from __future__ import print_function` can it?
Yeah, this was a very unwise thing to make, at least this could be postponed for later.
What? And make another language breaking version down the line? Better to rip off the plaster in one fell swoop.
It's better to make multiple breakages one by one than not doing them at all. On a plus side, maybe at some point you'd realize this print statement isn't that important anyway to make thousands of edits all over the world.
>I'm using the worst of both worlds

To me this is the main pain point and I'm surprised that people are not talking about this.

2to3 and 3to2 are too kludgy and writing native py2-and-py3 compatible code is quite painful and requires a number of workarounds (e.g. unicode/str/bytes type, different methods on dictionaries...)

Does the `six` library not help with this?
from __future__ import print_function on python2 solves the print function incompat.
Exactly this

Why is changing 'print stuff' to 'print (stuff)' such a big deal?

I think 2To3 solves a lot of print cases https://docs.python.org/2/library/2to3.html

To what end though? It's a small thing sure but it's busywork. Why am I being asked to do busywork?
Yeah, I don't like the busywork that Pep8 makes me do it, and it's a lot, and some of it is stupid, but it has to be done

You certainly don't have to do it if you don't want Python 3 and 2to3 makes it a lot easier

>Yeah, I don't like the busywork that Pep8 makes me do it, and it's a lot, and some of it is stupid, but it has to be done

Actually no, it hasn't. PEP8 is just a formatting standard, your code will work with your own standard too.

The print function is clearly a better, more precise way to handle it, to be sure...

But the print statement was one prominent, attractive way that Python was essentially pseudocode-- its removal seems an improvement from a pedantic sense, but one that seems to run contrary to convenience and (perhaps) the expectations of a beginner.

I disagree about this being worse for beginners - if we're teaching a new programmer about functions, surely a basic print function is a great introduction? Whereas before it was a one-off special case.
As a beginner, I ~hated~ the print statement. The print function had analogous syntax to all other functions, whereas the print statement always seemed to use some kludgy tricks.
Making print a statement again could break a lot of Python 3 code. In Python 2 it's a statement, and statements can't appear in lambdas. In Python 3 it's a function call, and function calls are expressions, which can appear in lambdas.

I don't think it could (easily) be resolved by treating it like a function when followed by parens and a statement otherwise. For illustration, consider what happens when you use parens after print in Python 2: the parens are treated like they would be in a mathematical expression — only there for the sake of order of operations. The parens effectively disappear when parsing.

There has actually been a lot of focus on making migration less painful, including restoring some removed features, e.g. Python 3.3 has added back the unicode literals. This is limited to things that are actually painful to migrate though not trivial non-issues like the print statement.
It's not really migration though, it's supporting both python 2 and 3. If you write modules that people depend on you're in a really, really painful spot with the 2 and 3 transition. You can have two completely separate code bases and deal with all the duplication and problems that come with it, or you can try to write code that works with both python 2 and 3 and deal with the huge amount of warts and pain that come with it. Both are painful so it's easy to see why a lot of people just don't even bother trying to support both and ignore 3.
I'm a library consumer not a maintainer, but with info like this- https://twitter.com/mitsuhiko/status/586294700430254080 If you look at the date on the calender, the fact this is still being discussed with virtually no progress like it's still 2008 when 3.0 got released tells me that this is over.

As an end user, I say drop 3.x support in your libraries. The gig is up. If 3 ever takes over, do a 1 time wholesale port and drop 2. Tell people who want 3.x support before then to port and maintain it themselves. Enough complaining.

> I say drop 3.x support in your libraries. The gig is up. If 3 ever takes over

People dropping 3.x support until 3.x becomes the most used version basically guarantees that it won't take over.

Is this a code equivalent to the bystander effect?

I don't think so. 3 will take over eventually if they don't give up on it. But the issue is that the onus of the labor involved is on those enthusiastic for Python3, and the core dev team.

Few to no one in userspace asked for this problem. For me, it's not a problem. I suspect a lot of people will eventually see it my way. Instead of learning/porting from 2 to 3, they'll stick with 2 and pickup something else like Go. I believe adding Go to my toolbelt was a much better use of my time. While there's other, maybe better, choices than Go, my argument is that it's so easy to learn that it's just about as difficult as the transition/porting of existing projects that Python3 would've been.

I personally gain little to nothing by spending any time on Python3. No amount of features, moving distros to 3 by default, or anything else can convince me. All job prospects 2, and all the libraries support 2. No one cares if my resume has Python3 on it, but adding Golang alongside Python2 opened up a lot of opportunities. If a Python(2) user wanted to spend time on Rust, that would also be a great use of time.

For each person I see demanding Python3 support, I want to see that person spending hours, weeks, months, porting everything they can find to 3 and then maintaining it. Because the rest of us don't care.

For me, Python3 has 1 main feature. It enables you to beg library maintainers to port to 3.

I agree migrating is painful, and supporting both even more so. But not because of print. Migrating print statement usages and even making them work on python 2 and 3 is trivial, even fully automated and statically verifiable.

Compare that to unicode changes, where you need to manually inspect and potentially deeply analyze every single string literal.

Why waste resources making the trivial easier just to please people that will not migrate anyway?

I don't mind print being a function so much, but rather the required parens. If they could somehow be optional, I'd bet 90% of the problems associated with the break would dissolve.
Why couldn't they have had a solution like with Fortran, where there are two incompatible versions with different file extensions? Then let projects be written in both .py3 files and .py files.