Python 2.7.18, the last release of Python 2
pythoninsider.blogspot.com
pythoninsider.blogspot.com
> time pypy mandel.py > pypy.pgm
seconds: 0.318101
real 0m0.426s
user 0m0.396s
sys 0m0.013s
> time python2 mandel.py > python2.pgm
seconds: 30.141954
real 0m30.156s
user 0m30.136s
sys 0m0.003s
That's just a silly Mandelbrot example, but for numerical algorithms like this PyPy is nearly 100 times faster than Python2, and that includes startup cost for the JIT!I'm not in any way associated with the PyPy project, but I can't help but believe a sane world would've moved from Python to PyPy in the same way everything moved from Brandon Eich's original JavaScript interpreter to the modern JIT ones like V8.
[0] https://doc.pypy.org/en/latest/faq.html#how-long-will-pypy-s...
I believe this is also a huge part of the reason why migrating from CPython version 2 to version 3 was delayed. I've adapted a few small C extension modules to run under both, and using #ifdef for the special cases to support both was unpleasant. So I imagine that any large package which needed to support both through the transition really suffered for it.
Years ago I had a bunch of code that was basically just matrix multiplication with some large-ish matrices, and then taking some eigenvectors/eigenvalues at the end. At the time I found the same thing -- if I decomposed things into simple lists of numbers for vectors and lists of lists PyPy was way faster.
I just had the opportunity to brush this code off in Python 3 and run it as-is, and it performs much better than it used to. But I am always curious to hear about these cases.
PyPy really is a wonderful project.
def mandel(data: np.ndarray):
c = data
z = c
for j in range(255):
z = z**2 + c
(from here: https://scipy-lectures.org/intro/numpy/auto_examples/plot_ma...)Moreover, for some very common things in signal processing, like working with evens/odds or left/right parts of an array, the parallel numpy operation will create lots of temporary arrays and copies.
And for what it's worth, your version of mandel should work with PyPy. So you can have your cake and eat it too.
EDIT: I should add the reason my code is "strange" is because I wrote it so I could do a one-to-one comparison with other languages which don't have builtin complex numbers. Maybe I should've cleaned that up before posting.
iiuc, this shouldn't be correct. given an ndarray A, `A[::2, 1::2]` will provide a (no-copy) view of the even rows/columns of A. Same with A[:len(A)/2] to get only half of A.
> And for what it's worth, your version of mandel should work with PyPy. So you can have your cake and eat it too.
Indeed, most of the scipy stack works with Pypy, it's great.
For instance, your Mandelbrot example doesn't even use views and it creates two temporaries the size of the entire array on each iteration:
for j in range(255):
t = z**2 # create a new squared array
u = t + c # create a new summed array
z = u # replace the old array
And all of this is ignoring how inconsistent numpy is about when it creates a view and when it creates a copy. z **= 2
z +=c
gets rid of the temps. But yes there are cases where that isn't possible.Explicitly unrolling loopy code (e.g., in pypy or Numba) is one easy way to achieve this, but you have to write more code.
Julia has some really nice syntax that lets you write things in this clean vectorized way but still get efficient code: https://julialang.org/blog/2017/01/moredots/
So in this case, NumPy would actually only make one temporary copy, effectively translating the loop into the following:
for j in range(255):
u = z**2 # create a new squared array
u += c # add in-place
z = u # replace the old arrayYes, and this is my fundamental complaint with the Python 3 transition. It took probably millions of engineer-hours, and the result was better Unicode support and a handful of minor features most of which could have been added to Python 2 just as easily. I suspect most users would gladly have traded those benefits for a 10x performance improvement.
Yes, and I wish the better Unicode support had been implemented similarly to how Go does it - one string type, and you use it to hold UTF-8 if needed. In other words, they could've simply deprecated the Python 2.X unicode object and added libraries to extract code points, or grapheme clusters, or perform normalization etc... This seems much simpler and more "Pythonic".
I guess everything is 20/20 in hindsight.
Different Unicode support. And worse bytes support.
What could previously be done using python -c "..." is now long, horrible and ugly.
I feel like you're the first person I've seen on the planet to echo my sentiments on these. I expect a lot of people will jump here to tell you you're wrong like they have to me, so just wanted to let you know I've felt exactly these pains and agree with you.
The fundamental problem as I see it is that "string" is a grossly leaky and misunderstood abstraction. The string type is not the same thing as a "text" type. It's being used in all the wrong places for that purpose. People treat "string" like it means "text", but in so many places where we deal with them, they just aren't (and should never be) text. Everything from stdio to argv to file paths to environment variables to "text" files to basically any interface with the outside world needs to be dealt with in bytes rather than text if you care about actually producing correct code that doesn't lose, corrupt, or otherwise choke on data.
C++ understood this and got it right, preferring to focus on optimizing rather than constraining the string type. Many other languages did pretty well by avoiding enforcing encodings on strings, too. And Python 2 defaulted to bytes as well, and only really cared about encoding/decoding at I/O boundaries where it thought it can assume it's dealing with text (though it sometimes didn't behave well there, and yes it got painful as a result). Then Python 3 came along and just made everyone start treating most data as if they're inherently (Unicode) text by default, when they really had no such constraints to begin with.
It boggles my mind that Python 3 folks like to beat the drum on how Python 3 got the bytes/unicode right without taking a single moment to even notice that most strings people deal with aren't (and never were!) actually guaranteed to be in a specific, known textual encoding a priori. They were just arrays of code units with few restrictions on them, and if you want to write correct code, you're going to have to deal with bytes by default (or something else with similar flexibility) instead of text. It would've been totally fine to introduce a text type, but it fundamentally can't take the place of a blob type, which is the language of the outside world.
Java uses UTF-16 throughout, including file paths. So does .NET. All Apple platforms are UTF-16. C++ - if you just look at stdlib, sure, it's byte-centric; but then look at popular frameworks such as Qt.
In practice, this means that, yeah, you can have that odd filename that is technically not Unicode. But the vast majority of code running on the most popular desktop and mobile platforms is going to handle it in a way that expects it to be Unicode. Why should Python go against the trend, and make life more complicated for developers using it in the process?
That HTML you just fetched? How do you know it's Unicode?
That .txt file the user just asked to load? How do you know that's Unicode?
For heaven's sake, when can you actually guarantee that even sys.stdin.read() is going to read Unicode? You can only do that when you're the one piping your own stdin... which is not the common case.
What do you do when your fundamentally invalid assumptions break? Do you just not care and simply present a stack trace to the user and tell them to get lost?
I've gotten tired of these debates though, so just a heads up I may not have the energy to reply if you continue...
Headers contain information about the charset. If the charset isn't specified then only god knows the used encoding. This applies to all encodings. If they aren't specified you can't interpret them.
>That .txt file the user just asked to load? How do you know that's Unicode?
If you don't know the used encoding then you simply cannot interpret the file as a string. If the encoding isn't specified you can't interpret the file.
>For heaven's sake, when can you actually guarantee that even sys.stdin.read() is going to read Unicode?
Again if the encoding isn't specified then all bets are off. This is an inherent problem with unix pipes. Text isn't any different than say a protobuffer packet. You have to know how to interpret it otherwise it's just a raw byte array without any meaning.
>What do you do when your fundamentally invalid assumptions break? Do you just not care and simply present a stack trace to the user and tell them to get lost?
I don't understand you at all. Just load it as a byte array if you don't care about the encoding. If you do care about the encoding then tough luck. You're never going to understand the meaning of that text unless it is an agreed upon encoding like UTF-8 and in that case the assumptions of always choosing UTF-8 are part of the value proposition.
Let me tell you why reading a text file as a byte array and pretending that character encodings don't exist is a bad idea. There are lots of Asian character encodings that don't even contain the latin alphabet. Now imagine you are running source.replace("Donut", "Bagel"). What meaning does running this function have on a byte array? It doesn't have any.
That operation simply cannot be implemented at all if you don't know the encoding. So if you were to choose the python 2 way then you would have to either remove all string operations from the language or force the user to specify the encoding on every operation.
A string literal like "Donut" isn't just a string literal. It has a representation and you first have to convert the logical string into a byte array that matches the representation of the source string. Lets say your python program is loading UTF-16 text. Instead of simply specifying the encoding you just load the text without any encoding. If you wanted to run the replace operation then it would have to look like something like this: source.replace("Donut".getBytes("UTF-16"), "Bagel".getBytes("UTF-16")). This is because you need to convert all string literals to match the encoding of the text that you want to replace.
Well, doesn't this cause a pretty huge problem? You now need to have a special type just for string literals because the runtime string type can use any encoding and therefore isn't guaranteed to be able to represent the logical value of a literal. Isn't that extremely weird?
Which was my entire point!! You have to go to bytes to get correct behavior. They didn't fix the nonsense by changing the default data type to a string, they just made it even more roundabout to write correct code.
> It just made it impossible to inadvertently treat bytes as a string in a certain encoding
It most certainly did not! It's like you completely ignored what I just told you. I already gave you an example: sys.stdin.read(). Uses some encoding when you really can't ever guarantee any encoding, or when the encoding info itself, is embedded in the byte stream is the normal case. How do can you know a priori what the user piped in? Are you sure users magically know every stream's encoding and just neglecting to provide it to you? At least if they were bytes by default, you'd maintain correct state and only have to worry about encoding/decoding at the I/O boundary. (And to top off the insanity, it's not even UTF-8 everywhere; on Windows it's CP-1252 or something, so you can't even rely on the default I/O being portable across platforms, even for text! Let alone arbitrary bytes. This insanity was there in Python 2, but they sure didn't make it better by moving from bytes to text as the default...)
Python 2.7.17 (v2.7.17:c2f86d86e6, Oct 19 2019, 21:01:17) [MSC v.1500 64 bit (AMD64)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> s = raw_input()
abc
>>> s
'abc'
>>> s + u"!"
u'abc!'
So it was bytes after reading it, and became Unicode implicitly as soon as it was mixed with a Unicode string. And guess what encoding it used to implicitly decode those bytes? It's not locale. It's ASCII. Which is why there's tons of code like this that works on ASCII inputs, and fails as soon as it seems something different - and people who wrote it have no idea that it's broken.Python 2 did this implicit conversion, because it allowed it to have APIs that returned either bytes or unicode objects, and the API client could basically pretend that there's no difference (again, only for ASCII in practice). By removing the conversion, Python 3 forced developers to think whether the data that they're working with is text or binary, and to apply the correct encoding if it's binary that is encoded text. This is exactly encoding/decoding at the I/O boundary!
The fact that sys.stdout encoding varies between platforms is a feature, not a bug. For text data, locale defines the encoding; so if you are treating stdin and stdout as text, then Python 3 will use locale encoding to encode/decode at the aforementioned I/O boundary, as other apps expect it to do (e.g. if you pipe the output). This is exactly how every other library or framework that deals with Unicode text works; how is that "insanity"?
Now, if you actually want to work with binary data for stdio, then you need to use the underlying BytesIO objects: sys.stdin.buffer and sys.stdout.buffer. Those have read() and write() that deal with raw bytes. The point, again, is that you are forced to consider your choices and their consequences. It's not the same API that tries to cover both binary and text input, and ends up with unsafe implicit conversions because that's the only way to make it look even remotely sane.
The only thing I could blame Python 3 for here is that sys.stdin is implicitly text. It would be better to force API clients to be fully explicit - e.g. requiring people to use either sys.stdin.text or sys.stdin.binary. But either way, this is strictly better than Python 2.
No, it's utterly false that every other framework does it. Where do you even get this idea? Possibly the closest language to Python is Ruby. Have you tried to see what it does? Run ruby -e "$stdout.write(\"\u2713\")" > temp.txt in the Command Prompt and then tell me you face the same nonsensical Unicode error as you do in Python (python -c "import sys; sys.stdout.write(u\"\u2713\")" > temp.txt)? The notion that writing text on one platform and reading it back on another should produce complete garbage is absolute insanity. You're literally saying that even if I write some text to a file in Windows and then read it back on Linux with the same program on the same machine from the same file system, it is somehow the right thing to do to have an inconsistent behavior and interpret it as complete garbage?? Like this means if you install Linux for your grandma and have her open a note she saved in Windows, she will actively want to read mojibake?? I mean, I guess people are weird, so maybe you or your grandma find that to be a sane state of affairs, but neither me, nor my grandma, nor my programs (...are they my babies in this analogy?) would expect to see gibberish when reading the same file with the same program...
As for "Python 3 forced developers to think whether the data that they're working with is text or binary", well, it made them think even more than they already had to, alright. That happens as a result of breaking stuff even more than it happens as a result of fixing stuff. And what I've been trying to tell you repeatedly is that this puristic distinction between "text" and "binary" is a fantasy and utterly wrong in most of the scenarios where it's actually made, and that your "well then just use bytes" argument is literally what I've been pointing out is the only solution, and it's much closer to what Python 2 was doing. This isn't even something that's somehow tricky. If you write binary files at all, you know there's absolutely no reason why you can't mix and match encodings in a single stream. You also know it's entirely reasonable to record the encoding inside the file itself. But regardless, just in case this was a foreign notion, I gave you multiple examples of this that are incredibly common—HTML, XML, stdio, text files... and you just dodged my point. I'll repeat myself: when you read text—if you can even guarantee it's text in the first place (which you absolutely cannot do everywhere Python 3 does)—it is likely to have an encoding that neither you nor the user can know a priori until after you've read it and examined its bytes. XML/HTML/BOM/you name it. You have to deal with bytes until you make that determination. The fact that you might read complete garbage if you read back the same file your own program wrote on another platform just adds insult to the injury.
But anyway. You know full well that I never suggested everything was fine in Python 2 and that everything broke in Python 3. I was extremely clear that a lot of this was already a problem, and that some stuff did in fact improve. It's the other stuff got worse and even harder to address that's the problem I've been talking about. So it's a pretty illegitimate counterargument to cherrypick some random bit about some implicit conversion that actually happened to improve. At best you'll derail the argument into a discussion about alternative approaches for solving those problems (which BTW actually do exist) and distract me. But I'm not about to waste my energy like this, so I'm going to have to leave this as my last comment.
Ruby is actually the odd one out with its "string is bytes + encoding" approach; and that mostly because its author is Japanese - Japan is not all sold on Unicode for some legitimate reasons. This approach also has some interesting consequences - e.g. it's possible for string concatenation to fail, because there's no unified representation for both operands.
Not really; they are similar in that they are dynamic scripting languages, but philosophically and in terms of almost every implementation decision, they are pretty radically opposed.
How many things are stored as binary files?
> All Apple platforms are UTF-16.
I'm glad all their executable files are apparently text files. How amazing.
> Why should Python go against the trend, and make life more complicated for developers using it in the process?
You tell me why Python3 did that.
Without fuzz? No, sorry, it was anything but.
First of all it would default encoding to "ASCII". Have any whiff of non-explicitly handled UTF-8 and it would just go bang at the worse time possible.
That was a stupid decision
"Oh but there was setdefaultencoding" Yeah here's the first result for that https://stackoverflow.com/questions/3828723/why-should-we-no...
So no, Python2 way of dealing with Unicode was the most annoying way possible, because hey who needs anything but ASCII right?
The part about defaulting to ASCII is annoying, yes. And using sys.setdefaultencoding to change the default would still be annoying, yes. The reason for that is that any default encoding will be annoying whenever the actual encoding when the program is running doesn't match the default.
The correct way to fix this problem is to not have a default encoding at all. Don't try to auto-detect encodings; don't try to guess encodings. Force every encode and decode operation to explicitly specify an encoding. That way the issue of what the encoding is, how to detect it, etc., is handled in the right place--in the code of the particular application that needs to use Unicode. It should not be handled in a language runtime or a standard library, precisely because there is no way for a language runtime or a library to properly deal with all use cases of all applications.
What Python 3 did, instead, was to change the rules of default encodings and auto-detection/guessing of encodings, so that they were nicer to some use cases, and even more annoying than before to others.
Whereas python3 is just waiting to explode the moment there are bytes in your UTF-8 that are invalid.
Oh the http request got truncated to leave invalid utf-8 in an otherwise fine utf-8 response? FUCKING ERROR.
There have been plenty of people with similar sentiments. I'm one of them. I have felt ever since I first looked at Python 3 that the ways in which it broke backward incompatibility were heavily skewed towards a few particular use cases and did not take into account the needs of all of the Python community.
Contrast with Java, which has made much more substantial changes to the language over all these years, but goes to great pains to support backwards compatibility. Upgrading major Java versions was never remotely as painful, and as a result, huge amounts of engineering time was saved.
There's so much whining, when they gave over 5 years to do the migration. I think the whole problem was that they gave too much time, and people were thinking it will be like that forever.
Also, Java is not a dynamic language, the type system allows for easy fix of issues like these, the python solution to do that is mypy, but it requires work by adding types.
You make it sound so generous of the Python maintainers to "give over five years" before breaking backwards compatibility--something that C, Java, JavaScript, C++, and probably most other languages haven't done for decades, or in some cases ever. Programming languages are serious basic infrastructure, programmer time is valuable, and Python's installed base is large enough that many man-centuries were probably wasted on this migration.
If the Python maintainers had not given as much time as they did, I doubt the Python community or ecosystem would have transitioned any more quickly than they did. More likely would have been some fork or alternate implementation of Python 2 becoming the new standard.
Reverse compatibility isn't free.
Unfortunately clang and gcc don't (yet?) have --safe or an x86-64-safe compilation target.
But yes the only people who wanted better unicode were web people. So they could have been better served moving to pypy.
I guess it's a matter of emphasis, but I'd say it has different Unicode support. It's better mildly for some use cases, but worse for others.
It's bloody horrible for one use case in particular: when you know the text is readable and mostly ASCII based and you are only interested in the ASCII bits, but don't know the encoding. That is the position you find yourself in for any designed in pre-unicode times, and that happens to include just about every file in a Unix file system.
The solution in those circumstances is to treat everything as bytes (b''). That wasn't even possible in the beginning. Now it mostly works, but all with hundreds of corner exceptions (like Exception messages, so you can't easily include a Unix filename in an error message).
Just do yourself a favor and migrate your codebase, Py3 is much more enjoyable to program in. I feel like all those vocal Python 2 supporters never had a chance to write a new code in Python 3. If you only did 2->3 migration you might hate Python 3, because it doesn't let you run a broken code that Python 2 happily executed, but if you can write Python 3 app from scratch you don't even notice the unicode, text is just text.
I think that's unfair. There was plenty of code that was out there for 10 years or more that was working completely fine and had to be ported. One of the most frustrating things I had to do was completely rearchitect some legacy binary file reading/writing because of the changes to how Python handled bytes. That code was out there as open source in the wild, stable, and was being widely used, and it basically required a full rewrite underneath the API.
One of the most frustrating things was that many packages we used as dependencies took ~5 years to port to Python 3, and then dropped Python 2 support immediately, leaving us with no choice but to use the old version for some time. We'd done a lot of the easy stuff already (2to3 on all files), but lots of the non-trivial things were the interactions with other packages so couldn't be touched until they had themselves got a Python 3 version.
A lot of packages were held back by early criticism of the move and the extended timeframe allowed to 2.x.
If 10% of the stop-energy dedicated to shit on 3 would have been put into supporting the effort, things would have gone differently. But most people dragged their feet and this is the result.
sudo apt install pypy3
and then pypy3 -m pytest /my/python/app
and if things go well you either got a 5-10x speed up or an insufficient test suite?If at this point you are still stuck on 2.7; you probably don't care a lot about updates in any case; including point releases. It's been well over a decade since it was made clear that this was going to end. So, IMHO the impact to remaining 2.7 users is minimal. They were in any case extremely conservative updating and are probably also running lots of other outdated stuff like Red Hat / Ubuntu versions that long dropped out of LTS, etc. That's fine and valid but at this point you shouldn't be surprised that you are on your own. If you didn't plan for this, that's on you.
From a security point of view that just means you probably don't want to run unprotected 2.7 servers running e.g. a web server. But otherwise it's fine if you shield it a bit. Lots of python is more about other types of jobs where the impact of security vulnerabilities is much less.
And, I'm sure that if there's demand, somebody might actually step up to do the occasional patch release if it is really needed. This has also happened in the Java world where several companies provide support for openjdk 6, 7, and 8 where Oracle no longer supports that (v8 stopped getting public updates already; you can still pay for some extended support but that too is being ramped down). I imagine, e.g. Red Hat might step up here as they seem to have continued to ship this for quite long and their LTS cycles might out run the python 2.7 cut off date.
I say it isn't a knock because I think they were equally fine with the goals: Perl was looking to make a bold break towards an unknown future [2], and Python wanted a very slow and sustainable migration.
I'm glad to see Python 3 go mainstream, I'm glad that Python 2 succeeded so well, and I'm glad there are segments of computer science that still throw mugs and aim for the moon.
[1] http://blogs.perl.org/users/ovid/2019/10/larry-has-approved-...
[2] https://www.nntp.perl.org/group/perl.packrats/2002/07/msg3.h...
It gave me at least a false sense of thinking Perl 5 was done and going to be replaced.
At the same time I found Python to be much easier to write, maintain and I became attached to the structure that PEP provided.
There were a lot of other factors that made me switch, but that particular point of not calling Perl 6 Perl made me think.
First, Perl will support multiple syntaxes that map onto a single semantic model. Second, that single semantic model will in turn map to multiple platforms.
Multiple syntaxes sound like an evil thing, but they're really necessary for the evolution of the language. To some extent we already have a multi-syntax model in Perl 5; every time you use a pragma or module, you are warping the language you're using. As long as it's clear from the declarations at the top of the module which version of the language you're using, this causes little problem.
There were even plans for a translator [2] similar to Python's 2to3 tool
Larry Wall and others are already working on a Perl 5 to Perl 6 translator, which will be able to translate (most) Perl 5 source code to the equivalent Perl 6 syntax.
In addition, Perl 6 will provide a "Perl 5 compatibility mode", allowing the compiler to directly execute any code that it recognizes as being written in Perl 5.
Integrating Perl code in Raku can be done with the excellent Inline::Perl5 module (https://modules.raku.org/dist/Inline::Perl5:cpan:NINE). In fact, that efficiency of that module basically killed the "parse Perl code in Raku" project.
It will be decades before the final Python 2 program goes offline.
The far bigger worry would be unexpected encoding issues corrupting the data when going from 2->3.
You're not wrong, but as a practical matter, that pretty much describes our entire industry.
You're right though, we're fighting our way out of technical debt and switching to python 3 was absolutely necessary. It's forced us to sort out a lot of sketchy string / bytes handling. We do, mercifully, have ~90% test coverage.
One issue with the test suite was that it made heavy use of a thing called django_any that isn't supported in python 3, so decided to replace it with Factory Boy. We have about 500 django models that needed new factories. Factory Boy works quite differently and it was a lot of work to make the factories behave similarly to the old ones where possible, and update most of our ~4000 tests for the new behaviour.
So that was one issue. It was tempting to just patch django_any, but we decided to tackle the technical debt instead.
Most codebases basically.
Canonical will not provide long term support for Python 2 as part of Ubuntu 20.04 LTS. In Ubuntu 20.04, Python 2 is a "universe" package [2] that does not receive updates by Canonical. This means that the you will only get Python 2 security update guarantees with Ubuntu is on 18.04 LTS until April 2023.
Debian is making an active effort [3] to remove Python 2 and packages that depend on it for its next release. It'll likely support Python 2 as part of Debian Buster until 2024.
Note that if you're reading this to delay your move to Python 3 by another few years, you're doing it wrong. This list shows even all slow enterprise-y distros have a deadline for Python 2, not that you can stretch your stuff for a couple of more years :)
[1]: https://access.redhat.com/solutions/4455511
Otherwise even if your python has security patches for next 4 years, it won't do you any good when you find a bug in one of your dependencies and bugfix is in a version that's python 3 only
Maybe they could call the new 2.7 interpreter IceSnake.
> As such, stating accurately that software ... is compatible with the Python programming language, or that it contains the Python programming language, is always allowed.
If redhat decided to add new features to python 2.7, I'm sure the PSF would make a stink
You probably confusing it with Tauton (a Python 2.7 with backported Python 3 features) that tried to place itself as Python 2.8. By backporting these changes they created essentially 3rd version of Python that was incompatible with other 2.
> During DebConf19 we¹ have tried to figure out how to manage Python 2 and PyPy module removal from Debian and below is our proposal. [0]
Debian are in the midst of a large project [1] to remove Python 2 as quickly as they possibly can. Whilst some bugfixes may happen, Debian are already telling you in no uncertain terms:
> port upstream package to python3
> remove any Python 2 use
[0] https://lists.debian.org/debian-python/2019/07/msg00080.html
Looks like Pillow has wheel for 3.8 now since April 2nd, so might work now (no compilation is needed). I don't know other packages so can't check them. Psycopg2 would probably be another one with this issue (also fixed on April 6th).
[1] https://pypi.org/project/Pillow/#files look for cp38 wheel files.
Mumble mumble something about conflating languages with implementations.
So your claim is that "Python 2" is a language spec, not an implementation? And that there will be future releases of this language spec in the future? I doubt it.
I agree it's likely that there will be people wasting their time maintaining an interpreter fork, but that will not be Python-the-language (a trademarked term BTW), it will be a fork of the implementation.
I suppose one could argue that, the CPython implementation is the language specification. (And I seem to recall hearing that notion somewhere years ago.) In which case, it would not be possible to freeze development of the language without freezing the implementation as well. There are various reasons I wholeheartedly disagree with such a characterization, but I guess there's some self-consistency there at least.
Development of CPython 2 has ended, bugs and all. It's past its end of life, this is well known and has been known for a long time. Any remaining bugs are the problem of the users, not the responsibility of the former developers.
Sure people will fork it and do stuff with those forks, but those will no longer be new versions of CPython, they will be new versions of some-fork-of-CPython.
PyPy maintains a Python 2 implementation and will continue to do so.
Cython, IronPython, Brython, Stackless Python, Nuitka, etc.
It will only get more difficult to maintain your app.
[1] https://python3statement.org/ - note many libraries weren't even waiting until 2020. It is a lot of work to maintain code with python 2 cruft. Not all packages are listed there, for example Django is Python 3 only, starting from 2.0 (currently at 3.0)
Sometimes it’s better to be correct and also yield to the common good.
(IIRC it used to do that in 3.0, but they backtracked very quickly - and 3.0 was effectively treated as a beta by the community at large, anyway.)
Now with Python 3 it's the other way around -- Windows is fine but Linux has issues. However, the problems for linux are less severe: often you can get away with assuming that everything is UTF-8. And you can still work with bytes if you absolutely need to.
No, they're not. Windows can't magically send your program Unicode. It sends your program strings of bytes, which your program interprets as Unicode with the UTF-16 encoding. The actual raw data your program is being sent by Windows is still strings of bytes.
> you can still work with bytes if you absolutely need to
In your own code, yes, you can, but you can't tell the Standard Library to treat sys.std{in|out|err} as bytes, or fix their encodings (at least, not until Python 3.7, when you can do the latter), when it incorrectly detects the encoding of whatever Unicode the system is sending/receiving to/from them.
> AFAIK neither sys.argv nor sys.environ had a unicode-supporting alternative in Python 2)
That's because none was needed. You got strings of bytes and you could decode them to whatever you wanted, if you knew the encoding and wanted to work with them as Unicode. That's exactly what a language/library should do when it can't rely on a particular encoding or on detecting the encoding--work with the lowest common denominator, which is strings of bytes.
Actually you can, you should use sys.std{in,out,err}.buffer, which will be binary[1]
> or fix their encodings (at least, not until Python 3.7, when you can do the latter), when it incorrectly detects the encoding of whatever Unicode the system is sending/receiving to/from them.
I'm assuming you're talking about scenario where LANG/LC_* was not defined, then Python assumed us-ascii encoding. I think in 3.7 they changed default to UTF-8.
That's fine for your own code, as I said. It doesn't help at all for code in standard library modules that uses the standard streams, which is what I was referring to.
> I think in 3.7 they changed default to UTF-8
Yes, they did, which is certainly a saner default in today's world than ASCII, but it still doesn't cover all use cases. It would have been better to not have a default at all and make application programs explicitly do encoding/decoding wherever it made the most sense for the application.
I'm not aware what code you're talking about. All functions I can think of expect to provide streams explicitly.
> Yes, they did, which is certainly a saner default in today's world than ASCII, but it still doesn't cover all use cases. It would have been better to not have a default at all and make application programs explicitly do encoding/decoding wherever it made the most sense for the application.
I disagree, it would be far more confusing when stdin/stdout/stderr were sometimes text sometimes binary. If you meant that they should always be binary that's also unoptimal. In most use cases an user works with text.
All the places in the standard library that explicitly write output or error messages to sys.stdout or sys.stderr. (There are far fewer places that explicitly take input from sys.stdin, so there's that, I suppose.)
> it would be far more confusing when stdin/stdout/stderr were sometimes text sometimes binary
I am not suggesting that. They should always be binary, i.e., streams of bytes. That's the lowest common denominator for all uses cases, so that's what a language runtime and a library should be doing.
> If you meant that they should always be binary that's also unoptimal. In most use cases an user works with text.
Users who work with text can easily wrap binary streams in a TextIOWrapper (or an appropriate alternative) if the basic streams are always binary.
Users who work with binary but can't control library code that insists on treating things as text are SOL if the basic streams are text, with buffer attributes that let user code use the binary version but only in code the user explicitly controls.
> And, well, if you’re already making a backward-incompatible version, here’s this checklist of other breaking changes you might as well bring along for the ride.
Sorry, that doesn’t track. Treating quoted strings as UTF-8 by default instead of ASCII-or-arbitrary-bytes would have been a small migration that would not have taken over a decade to complete.
When python was written in 1989 Unicode didn't exist yet.
As for your second argument, many people bring out Go, that had such amazing idea of using everything as UTF-8 and it works great. They don't realize that Go is pretty much doing the same thing that Python does (ignoring how the string is represented internally, since that shouldn't really be programmer's concern).
Go clearly distinguishes between string (string type) and bytes ([]byte type) to use string as bytes you have to cast it to []byte and to convert bytes to string you need to cast them to string.
That's the equivalent of doing variable.encode() to get bytes and you do variable.decode() to get a string.
What python 3 inroduced is two types str and bytes, and blocked any implicit casting between them. That's exactly same thing Go does.
The only difference is implementation detail, Go stores strings as utf-8 and casting doesn't require any work, they are just for having compiler catch errors it also ignores environment variables and always uses utf-8. Python has an internal[1] representation and does do conversion. It respects LANG and other variables and uses that for stdin/out/err. Initially when those variables were undefined it assumed us-ascii which created some issues, but I believe now that was fixed and utf-8 is the default.
[1] Python 3 actually tries to be smart and uses UCS1 (Latin 1), UCS2 or UCS4 depending what characters are contained. If an UTTF-8 conversion was requested it will also cache that representation (as a C-string) so it won't do the conversion next time.
That was me in a parallel thread. Java and JavaScript internally use UTF-16 encoding. I also mentioned C, which treats strings as byte arrays, and C++, which supports C strings as well as introducing a string class that is still just byte arrays.
> As for your second argument, many people bring out Go, that had such amazing idea of using everything as UTF-8 and it works great.
Has Go ever broken backwards compatibility? Let me clarify my second argument: if you are going to break backwards compatibility, you should do so in a minimal way that eases the pain of migration. The Python maintainers decided that breaking backwards compatibility meant throwing in the kitchen sink, succumbing to second system effect, and essentially forking the language for over a decade. The migration from Ruby 1.8 to 1.9 was less painful, though in fairness I suppose the migration from Perl 5 to Perl 6 was even more painful.
That being sad, you can integrate Perl code in Raku (using the Inline::Perl5 module), and vice-versa.
C and C++ doesn't really have Unicode support, and most C and C++ applications don't support unicode. There are libraries that you need to use to get this kind of support.
> Has Go ever broken backwards compatibility? Let me clarify my second argument: if you are going to break backwards compatibility, you should do so in a minimal way that eases the pain of migration. The Python maintainers decided that breaking backwards compatibility meant throwing in the kitchen sink, succumbing to second system effect, and essentially forking the language for over a decade. The migration from Ruby 1.8 to 1.9 was less painful, though in fairness I suppose the migration from Perl 5 to Perl 6 was even more painful.
Go is only 10 years old Python is 31. And in fact it had some breaking changes for example in 1.4, 1.12. Those are easy to fix since they would show up during compilation. Python is a dynamic language and unless you use something like mypy you don't have that luxury.
Going back to python, what was broken in Python 2 is that str type could represent both text and bytes, and the difficulty was that most Python 2 applications are broken (yes they worked fine with ascii text but broke in interesting ways whenever unicode was used. You might say, so what, why should I care if I don't use Unicode. The problem was that mixing these two types and implicit casting that python 2 did made it extremely hard to write correct code even when you know what you're doing. With python 3 is no effort.
There is a good write up by one of Python developers why python 3 was necessary[1].
You know, it’s astounding to me that you managed to quote my entire point and still didn’t even bother to acknowledge it, let alone respond to it.
If they had to break backwards compatibility to fix string encoding, that’s fine and I get it. That doesn’t explain or justify breaking backwards compatibility in a dozen additional ways that have nothing to do with string encoding.
Are you going to address that point or just go on another irrelevant tangent?
That is because you can easily use Perl5 modules in Raku.
use v6;
use Scalar::Util:from<Perl5> <looks_like_number>;
say ?looks_like_number( '5.0' ); # True
Which means that all you have to do to start migrating is make sure that the majority of your Perl codebase is in modules and not in scripts.Then you can migrate one module at a time.
You can even subclass Perl classes using this technology.
Basically you can use the old codebase to fill in the parts of the new codebase that you haven't transferred over yet.
---
By that same token you can transition from Python to Raku in much the same way. The module that handles that for Python isn't as featurefull as the one for Perl yet.
use v6;
{
# load the interface module
use Inline::Python;
use base64:from<Python>;
my $b64 = base64::b64encode('ABCD');
say $b64;
# Buf:0x<51 55 4A 44 52 41 3D 3D>
say $b64.decode;
# QUJDRA==
}
{
# Raku wrapper around a native library
use Base64::Native;
my $b64 = base64-encode('ABCD');
say $b64;
# Buf[uint8]:0x<51 55 4A 44 52 41 3D 3D>
say $b64.decode;
# QUJDRA==
}
{
use MIME::Base64:from<Perl5>;
my $b64 = encode_base64('ABCD');
say $b64;
# QUJDRA==
}
{
use Inline::Ruby;
use base64:from<Ruby>;
# workaround for apparent missing feature in Inline::Ruby
my \Base64 = EVAL 「Base64」, :lang<Ruby>;
my $b64 = Base64.encode64('ABCD');
say $b64;
# «QUJDRA==
# »:rb
say ~$b64;
# QUJDRA==
}
I just used four different modules from four different languages, and for the most part it was fairly seamless. (Updates to the various `Inline` modules could make it even more seamless.)So if I had to I could transition from any of those other languages above to Raku at my leisure.
Not like Python2 to Python3 where it has to mostly be all or nothing.
# declare that the code itself is written in utf8
use utf8;
my $ā = 'ā';
If you need unicode strings to work, you turn on the unicode strings feature. use feature 'unicode_strings';
Another way to turn it on: use v5.12;
(Declaring which version of the language you need is something you should do anyway.)Really mostly what you have to do is declare the encodings of the file handles.
# change it for all files
use open ':encoding(UTF-8)';
To change it per file handle, you would use `binmode`. (Which was originally added to allow binary code to work on Windows.) open my $fh, '<', 'example.txt';
binmode $fh, ':utf8';
(Declaring the encoding of an opened file is something you should do anyway.)---
Basically Perl just defaults to the old original ways. If you need a new feature which would break old code, you just declare that you need it.
Because of that, most code that was written for an earlier form of Perl still works on the latest version.
Unless some python 3 fanatic goes out of his way to write a python 2 library deleting virus the existing code wont disappear. Also some of these pledges only limit feature releases, afaik numpy planned to still provide a long term support version with bugfixes for python 2. It also helps that python already comes with a lot of build in bells and whistles so third party libraries aren't always necessary either.
You might be lucky and someone else might do that for you, but it will be harder and harder with time. Already according to JetBrains survey in 2019 (I believe) about 80% of people surveyed they already use python 3.
As for numpy I just checked[1] and the only wheels they are providing for the latest version are 3.5+ the package also says that it is 3 only.
effort += 1 + 1
Ported to Python3 for you.
effort = (effort := effort + 1) + 1But if you actively changing the code, the maintenance will get more and more expensive. With packages dropping python 2 support if you discover a bug in one of your dependencies and fix is in package that no longer work on python 2 you'll need to backport the fix (and maintain your fork) or migrate your code.
Too many software development projects are treated as one-off events where people commission them and assume they will work forever without updates. Software requires maintenance, and people who commission software development projects without planning on how they are going to be maintained in the future are taking on risk. Any risk involved in updating that abandoned code in future is a consequence of that decision.
One industry example is https://vfxplatform.com/ - they just (this year) moved to Python3, but with some delays, from the site:
The move to Python 3 was delayed from CY2019 to CY2020 due to:
No supported combination of Qt 5.6, Python 3 and PySide 2 so Qt first needed to be upgraded.
Upgrade of both Qt and Python in the same year was too large a commitment for software vendors and large studios.
Python 3 in CY2020 is a firm commitment, it will be a required upgrade as Python 2 will no longer be supported beyond 2020. Software vendors are strongly encouraged to provide a tech preview release in 2019 to help studios with testing during their Python migration efforts.I heard that some places still using Turbo Pascal for DOS and have to stick with 32 bit machines because 64 bit can't run 16 bit DOS code.
I'm not looking forward to the scramble when it does upgrade, as we're using a ton of community modules that may or may not be abandoned.
Audit all strings coming in and going out for encoding issues. Update all dependencies to their python 3 equivalent. Replace dependencies that hadn’t been updated (typically older django dependencies). Use python-future to bulk update incompatibilities. Changes to metaclasses were annoying. Force all uses of pickle to use protocol version 2. I documented some more during the migration on Twitter https://twitter.com/jarshwah/status/1209381850822496256?s=21
We began getting the code base into a compatible position about 1.5 years earlier. A final push of 3-4 weeks of work got it over the line, with many bug fixes after the deployment.
Other older larger systems will have similar problems at a larger scale.
This isn’t a condemnation by the way. Python 3 is better. The only reason we held out so long was because of the business justification. Once we couldn’t wait any longer it got prioritised.
"It's a dirty job, but someone's got to do it".
The string-handling changes, while necessary, are also a bear to deal with. Since python is dynamically typed, you need to work to find all the places where you need to add a ".decode()" or ".encode()". If you don't have excellent test coverage already, you're going to miss some, and it'll be a game of whack-a-mole until you get them all... assuming you have actually gotten them all.
Enumeration order in dict keys was never guaranteed (until 2019), even on 2. So basically that code relied on undocumented cpython behaviour that was strongly advised against, i.e. it was broken already. 3 simply made the brokenness more visible.
Dicts were by definition unordered until Python 3.7 [0], so you were relying on undefined behaviour. If you need an ordered dictionary and support Python 3.6 or below, you should use OrderedDict [1].
[0] https://mail.python.org/pipermail/python-dev/2017-December/1...
[1] https://docs.python.org/3/library/collections.html#collectio...
Although there are ways, you can still incrementally adapt code base to work on both pythons. Also pylint with py3k option, mypy can help. There's also six packages, but many people seem to had good luck with futurize.
There's also something that I tried a while ago and it surprisingly worked (although it might not work that well on larger codebase?), basically you can use Cython (not to be confused with CPython) to compile Python 2 code and then include it in python 3, this would enable migration file by file.
Knowing researchers (at least in academia), they're the last people I would expect to change.
But now we're back on that treadmill...
Man in 2020 if you are SSHing between boxes and upgrading python by hand, you really should invest in some devops. Even 5 hours a week.....
Still a lot easier to manage as docker volumes in k8s.
Our applications are mostly monoliths and the number of servers they use is quite constant.
But it does mean our Python version really only changes when we switch to the next Ubuntu LTR, and isn't always the same between different projects.
Well. The container doesn't magically update itself. But FROM python:3.6 -> FROM python:3.8 doesn't seem that hard. Then again a flexible package manager (with recent repos) can do this as well.
I control what is installed on it.
Thankfully it's no longer my problem.
pygame supports python3 since 2016, python-opencv since 2018 at least
> I think Python 3.7 to 3.8 was change my docker version and push to CI
I do strongly feel that removing functions from the core library is a huge no-no for point releases.
Adding new features will seldom break old stuff. It is the removing part that is hard.
(With the exception being when like a variable broke because it became a keyword, but if you made a variable something like async I am not sure you are entirely innocent).
The old version you implicitly claim is better isn't, it just doesn't have the warnings from their dependencies in place yet.
The warnings are useless if they're not from my code, so they get turned off once globally.
Yes, it is not your package that is responsible, but it still affects your application, you could open a ticket, or submit a PR. If you had that message you should also hold of with upgrading to newer python until this is resolved.
No, you idiot. It's a deprecated usage in a dependency.
What happens in the future is I update pandas, it stops using the deprecated numpy method, and the warning just disappears with very little action on my part.
It's a useless warning.
And submit a PR every time this happens? How about I request you pull me?
> If you had that message you should also hold of with upgrading to newer python until this is resolved.
1. Upgrading to newer python? Who fucking cares
2. Upgrading resolves the warning entirely.
Python 3.3 was release in 2012. You've had 8 years.
The OP should have dropped it because it's unmaintained, and a maintained replacement has existed for a long time: https://cryptography.io/
This is an especially important consideration for security-critical libraries like cryptographic libraries.
Pypi has an api (https://pypi.org/pypi/<pkg-name>/json) that can be leveraged to implement alerts like "this pkg last released 5 years ago, it might be dead!". I guess that's what the "security" package uses already. It would be cool if they added an option to report on this sort of thing.
> Deprecated since version 3.3, will be removed in version 3.8: The behaviour of this function depends on the platform: use perf_counter() or process_time() instead, depending on your requirements, to have a well defined behaviour.
I would be wary of any crypto library that continued to work with a warning for 8 years and no one bothered to fix it. Most likely no one was maintaining it.
It would be nice if library developers kept their code up to date, but that doesn't always happen. Python core devs know this; well all know this, yet they consciously screw with the core libraries with the principle, caveat emptor.
I don't understand why they don't ear-mark these changes for 4.0. These kind of things are a universal frustration with the community and they are so easily avoidable.
If I don't want to use OS packages, I have to decide to package, build, deploy, and maintain the Python packages, often in a way that separates it from the system Python package, while also managing any Python libraries we need (some of which may be C extensions and require compiling).
Whenever possible, I like to leverage upstream packaging so that I don't have to track security updates on my own.
I say this as someone who used to maintain the official Python.org RPM packages.
python3 -c "import ast; print(ast.arguments([]).args)"
It seemed completely unnecessary too. They could've just kept the structure the same across minor versions...The python despite having 3 digit versions apparently is not following semantic versioning. The major version number generally had not much significance (the python 3 was exception, 1->2 and what they are assuring us 3->4 won't be a big change)
"The ast module helps Python applications to process trees of the Python abstract syntax grammar. The abstract syntax itself might change with each Python release; this module helps to find out programmatically what the current grammar looks like."
This module is a bit special, because as they say, it supposed to reflect current python grammar. If they change grammar and didn't make it reflect it it would lead to different kinds of issues.
Lest you think informing users more clearly is a foreign concept to them, look at the dis module [1] for comparison. They're extremely clear the whole thing is implementation detail of CPython. If anything, after reading that, one would think your conclusion would be "ah, I should program against the AST then, not the bytecode". So you do that and then you're greeted with this nonsense! Obviously it's your fault for assuming there's anything stable to program against across minor releases.
This module exposes internals of python, and providing such guarantees would cripple development, because it wouldn't even allow for refactoring the code.
Most languages don't run into this because they don't expose internals like that. You typically extract that yourself and you accept it can change every release.
As for dis, that's very different, the bytecode is just an optimization of the CPython, python code could work perfectly fine without it, the bytecode was introduced to make it faster and other implementation won't use I would imagine that Jython and IronPython most likely don't implement it since they have their own (JVM and .NET)
ast on the other hand is expected to be identical if a language claims to be compatible with a given version, and you would expect PyPy for example to also provide this package.
RIP, python2, you will be missed. And a big thank you to all the contributers who have kept it alive for so long!
> On the #raku channel on Freenode, several users are using Raku in production.
Ask the PERL and PHP communities how hard it is. PHP 6 ended up getting dumpstered and the “next” version of PERL was so different they had to change the name and the community never really recovered. Python has at least grown/ survived through the upgrade.
It's only relatively recently that Python 3 passed a certain threshold that made deprecation of Python 2 something that could actually be executed upon. Had the growth been slower in the last five years I think the timeline would have been different.
If I was going to critique Python "failures" I think the bigger target for me would be the integration of async concepts into the platform and language. This could have been handled more smoothly and with better community cohesion, but most HNers only have a superficial understanding, i.e the GIL is bad and Python can't compete with Go.
[1] http://python-notes.curiousefficiency.org/en/latest/python3/...
It was an immense amount of work for a fairly small payoff.
Also, it takes pretty vivid imagination / stout obstinance to characterize vast majority of pre-existing libs/projects and almost all new project starts using new version as a "failure".
Bunch of whining and FUD does not equate to failure.
What example would you point to as a bigger failure?
Perl ranks up there at the top of 'lists of programming languages people love to hate.'
Python is now roughly #1.
Let the data tell the story, and not the other way around.
Everyone who ships software knows that there is always a very small but disproportionately vocal set of malcontents who can't accept changes; that's their issue, not anyone else's.
Anyone who thinks they do should go sign up for some COBOL training so they can grab those sweet New Jersey contracts. ;)
Like I said, I acknowledge there were costs to transitioning. Python 3 was pretty rough around the edges upon first release. But that first release was in 2008 ...
I realize not everyone needs to upgrade, and that's totally fine. But how people internally justify the cost of keeping Python 2 going when the momentum and most of the community is with Python 3 I cannot understand. Unless you're in a very inflexible corporate setting ...
It's just a tough sell to manually update a huge pile of code that works just fine as-is. No new features will be introduced. No bugs fixed, while some new ones may pop up. There's a lot of manual work in porting, the automated tools only cover the basics. Your downstream customers receive very little benefit for this effort, which makes it very hard to justify spending the engineering resources on it.
I also appreciate that there are a small number of projects (e.g. PyPy) that probably do require some of the special sauce around CPython 2.
But for everyone else ... come on folks. We're developers and engineers, we're supposed to be the creative builders of tomorrow and all that stuff. Is this really so hard?
Absolutely, especially when there is no tangible benefit to doing so. At $day_job it took us over a month to convert our codebase to Python 3 (bit by bit, not all at once), and we still ended up running into errors in production. In our case, we were forced to make the switch because we needed to upgrade some libraries that had dropped Python 2 support, but there is plenty of software out there that Just Works™ and nobody wants to touch it (for good reason!). In those cases, it's way less expensive to pay someone to maintain the interpreter than it is to take on the effort of a full blown conversion.
Once we did as much as we could do on Python 2, we had one of our engineers maintain a separate Python 3 branch in a staging environment for a while (maybe two weeks?) that we did some heavy QA on. And once we were fairly confident in the results, we merged and released that over a weekend and fixed issues as they came up.
We did all of this once for each service, but the bulk of the work (>80%) was our legacy monolith. I think the whole thing would have taken way less time with better test coverage, but alas. :)
It's possible that this might be more work that if you would use pylint, mypy, python-future. Also it probably won't work if your code tries to be clever and does some import hacking (although who knows, maybe it still would work)
90% of computer engineering isn't writing software. It's logistics, organization, and incentives.
For Python 3, I think it fell down hard on incentives. It was better, but not better enough to justify rewriting code that worked for a lot of teams, for a lot of years.
When you go to make incompatible changes and you find your userbase kicking and screaming against following you, that's not a technological problem, but it is a problem.
Languages need to serve their users, not the other way around. A lot of us really didn't care about minor syntax tweaks and we didn't need a lot of the new features. What we needed was better performance and a better deployment story, and we have received neither.
At this point, I've helped port multiple code-bases in multiple companies. Porting to Python 3 actually can and does fix some bugs, as it generally forces the code to start handling text semi-correctly, instead of just hoping the bytes go through and it all works out.
> Your downstream customers receive very little benefit for this effort,
They do, actually. Again, while I was porting those same code-bases, I'm working with a team of engineers who (and along with myself) are also still adding code to meet other incoming requirements. And in my experience, there was a fair bit of "Boy, it'd be nice if X were easier in Python!" where X is something that is easy in Python … 3. The question would have often gone unanswered had we not had devs experienced with Python 3 on the team.
Porting to 3 gets you all the additions that have come to Python that haven't been backported. A better standard library, syntax that better supports you, etc., translate to better productivity for devs as they are now equipped with better tools. This is only going to get worse as libraries drop support for 2.
(And while many things have been backported into third-party libraries, not all of them have, and in particular, syntax changes. And the existing backports are actually quite useful during the process of porting: I can change the code to conditionally depend on the backport library in 2, and use the real deal in 3.)
It is not universally applicable, however. There's a lot of old code that, as I said before, is just fine. Adding a 100 line feature in the old version is easier than porting the whole 10,000 lines over. Just ask COBOL programmers what they're up to right now - it's not porting to a modern environment, it's maintaining the old one.
The other major issue is that Python 3 really didn't fix the major issues with Python that persist to this day. Atrocious byte code performance, a really awful deployment story, and perennial favorite: the GIL. Had just one of these been tackled in Python 3, the migration probably would've happened a lot faster. You might not care about those problems or they may not be problems for you, but they are for some of us and they persist to this day.
I will concede that on the whole, Python 3 is a better Python. But it's not 2x or 3x better. It's 10-20% better, and that's a tough sell to a busy engineer who has better things to do. I can't justify spending time on anything that is a mere 10% improvement when I have a pile of 2x improvements to work on.
Which one of those two languages will give me No Module Found when I go to import openCV?
Different features, different uses, mutually exclusive, python2 and 3 are different languages.
Why did I not see this sentiment for C89 vs C99 for example?
Guess what's going to happen for the next 10+ years?
Let me be clear: If people want to use Python 2 they can go nuts. They can even pretend it's a completely new language if they want to. If there's enough of them I'm sure it can be done. Just stop asking the community to support it, or the rest of us to care.
So it's PSF's fault for not providing a -std=py2 option? I guess that's a sensible way to look at it.
Also, all the world wasn't unicode at the time and still isn't (unfortunately, IMO, but still the case). We still have customers using various non-Unicode encodings and not all characters have a 1:1 encoding/decoding round-trip through Unicode.
The part about Unicode is about how much Python 2 code accidentally only handled ASCII. Python 2 requires handling other encodings as bytes anyway.
I strongly disagree. I actually tried using unicode correctly in python 2, it is actually quite hard. It's similar to using memory safely in C, it is possible, but there are many gotchas.
In python 3 all of this is done with no effort.
Software using Python 2.7 won't magically disappear and I believe there is going to be a demand after fixes.
(I know about Tauthon but I don't think it applies here ...)
I'm willing to bet that the demand is not really there and most of this is just kvetching. Should have happened a long time ago.
I'm not aware of any good technical reason to still be using Python 2. There is the "I don't have time to upgrade" argument, and I recognize the cost is real. But now we'll see at last if people are willing to stick up for Python 2 more than just figuratively.
The industry is still not in the process of porting major pieces of the ecosystem.
It’ll be another 3-5 years i estimate
Demand for fixes will occur but it would probably best be handled by a third party that would specialize in that or developing it internally.
(most places i've worked at, when we do the calculations for the business it's much cheaper/less risky just to upgrade to python 3, rather than to support python 2 or switch languages)
Python 2 has paid the bills for over a decade, but I love writing Python 3.8 so much more. I even love the walrus operator. We’re in the process of upgrading, finally.
https://github.com/python/cpython/commits/2.7
This is the release of the changes up to that date, since they don't release instantly.
https://adtmag.com/articles/2020/01/09/python-2-end-of-life....
> As of January 1st, 2020 no new bug reports, fixes, or changes will be made to Python 2, and Python 2 is no longer supported. We have not yet released the few changes made between when we released Python 2.7.17 (on October 19th, 2019) and January 1st. As a service to the community, we will bundle those fixes (and only those fixes) and release a 2.7.18. We plan on doing that in April 2020
[1] Sunsetting Python 2: https://www.python.org/doc/sunset-python-2/
[2] When is the last release of Python 2.7 coming out?: http://python-notes.curiousefficiency.org/en/latest/python3/...
Once you're using containers, shared build tooling, and enforcing linting/testing, the version you use doesn't matter as much, imo. Unless you're using an advanced feature that's still developing (rare..only seen it a few times), most projects can upgrade minor version with zero codebase changes. Just lock a new environment, format code, and push to CI.
Fix't it for ya.
If you actually look at the issue discussing this, you can see that Guido is being more than amenable and the responses are honestly verging on childish.
IMO, Python 2 is a genericized trademark like Kleenex at this point.
And have the Python maintainers ever claimed that there's no interest in a community-maintained Python 2?
Kleenex is often used to refer to facial tissue, regardless of manufacturer of the facial tissue.
Python 2 is used to refer to one of the releases of the CPython 2 interpreter, most often the latest release, with earlier releases typically referred to with their first point (e.g. "2.6" as I've seen elsewhere in this thread). People rarely refer to Pypy or Jython as "Python 2", at least in my experience. They may refer to compatibility with a point release of the official CPython.
For example, Pypy describes itself as with the following:
> PyPy implements Python 2.7.13 and 3.6.9. It supports all of the core language, passing the Python 2.7 test suite and most of the 3.6 test suite.
They're not saying PyPy is Python 2, rather that it implements the programming language represented by point release Python 2.7.13. Elsewhere, they talk about compatibility with Python. Nowhere do the PyPy developers refer to their product as "Python 2".