What happened to Python?
charlesleifer.com
charlesleifer.com
> Did Python sell out? I don't know. Maybe Guido caved to some persuasive people with bad ideas. Maybe communists, wanting to reduce global productivity, railroaded through all these garbage PEPs. Maybe Python wanted to throw off its reputation as a toy language and become a serious language like Node.js... Whatever the case, when I look at all the PEPs that have been accepted over the past couple years, I can see that the inmates are now running the asylum.
If you and a billion other people want Python2 so badly, fork it and keep developing it. If the maintainers want to push a language in one way, that is their prerogative! It is their time they are using.
Seriously. If all of the time spent on whining on the Internet about how python3 killed the dinosaurs was used to make a python2 interpreter, a viable fork would already exist.
I mean, there's allegedly a great economic incentive for it, right? All of these business-critical python2 apps are out there, so the whiners claim, you'd think somebody would pay for one if it was actually so much better than python3.
(FTR I'm one of the folks that think Python 3 is an improvement over Python 2 but we still have a monster 2.7 code base that won't be ported any time soon).
There was a whole lot of wailing about how the changes were unnecessary, and a whole lot of complaining about how expensive it was going to be to rewrite all this existing code. It was all very visible, but if you paid too much attention to it you'd fail to notice that there was also a huge and quiet majority of people who recognized that VB.NET was a much more capable language that allowed people to easily go places they could barely have dreamed of with VB6. I suspect those people were so quiet because they were too busy doing useful work like keeping their toolchain up-to-date to spend much time griping on the Internet.
So on the Python side of things, it's the exact same story. I see plenty of blog posts and suchlike by people who are still upset about Python 3, but I'm hard pressed to met someone who feels that way in real life. Most folks I know made the switch ages ago, and are a bit mystified that this whole thing is still such a big deal.
I actually use VB.NET at work to strong effect. It enables us to hire domain experts (insurance) and have them working as developers in a week. And you get the full .NET compatibility to networking for updates, PDF libraries, crypto, etc. Everything you'd need for a first class desktop app, with much greater freedom on who you can hire (compared to Java, c#, etc).
But I'd never dream of wanting to build a "weekend app" in VB.NET anymore. You're basically stuck with a very heavy IDE, to fill in boilerplate and do builds. And there's lots of framework churn here so a template you'd have from 2011 would probably be a huge pain to try and implement today.
Never used VB6, but from what I understand it, it was a huge productivity tool: any small task could get coded up and shipped in a day. That's how I think of python right now, I don't want to see it go the way VB. We already have enough enterprise ready type languages, not everyone has to be one.
I guess when 2020 comes around, we'll be shell-shocked to find that python 2.7 isn't supported anymore, and we'll find some unofficial package source for python 2.7 that will keep us afloat for a few more years.
/ducks from downvotes
Enthusiasm and passion do not a viable fork make. The number of people who are truly able to grok and work on the core of Python2 who are not already working for the PSF can probably be counted on one hand, without using all of your fingers.
> you'd think somebody would pay for one
And yet such fundamental projects like NTP and OpenSSL show that need and use does not create money for those projects. Instead, those with money or time create their own versions (Apple, Google, BSD).
If nobody affected by python2 is going to pay for a python2-fork, python2 must not actually be very important. And yes, PSF might have all the brain trust now, but it's not like a big company whose continuity-of-business really depended on python2 wouldn't attempt to acquire this expertise in some fashion. "Acquire" meaning something as simple as picking a few engineers on staff and saying "learn everything you can about this so we can maintain our own version."
def hello_world(name: str) -> None:
print("Hello", name)
Which is completely fine. There'd be no point in using asyncio.The new Python fork would have none of Python's fame and it would need some push to solve the chicken-egg problem. Why fork and maintain a huge code base when nobody will use it?
It was the original maintainers who forked MariaDB off MySQL over a concern for software openness, which sounds like a good reason to fork.
A python2.7 fork will have no reason other than "We don't want to use the new version of the language". I doubt if any Linux distros would replace their python2.7 package with the fork, even after the EOL of 2.7.
While the typing thing has been discussed here yesterday[0], I share his views about asyncio.
I was a bit disappointed when asyncio lost its provisional status in Python 3.6. I was hopping that the community will wait a bit more and settle on something else.
The work that David Beazley does on Curio[1] is amazing. This should be an inspiration for the standard library in my opinion.
I often find myself going through the standard library documentation and it's a real pleasure to read and discover things that I didn't know were just an import away.
I use the standard json module all the time and I never felt like it was holding me back. I don't write performance critical software so I tend to value the simplicity more than the performance gain.
Yes, if you want to write a system of asynchronous functions with type decorations, then yes it can get a little messy. But this isn't Python becoming less "austere and easy to read" over time, this is just identifying a case where Python is less readable than one might like.
I'm not sure what to tell you if you were looking to write asynchronous code without some amount of syntactic cruft. There are languages that can do this with a prettier syntax and less boilerplate (Go, maybe). But I don't think has ever included any version of Python.
I've embraced type hints. Although they have no run-time effect, there is a command line tool called mypy which enforces correctness. It has caught more than a few errors for me. Declaring the types of arguments and return values is a help when reading the code imo.
It's true that most of these new features are optional, but that doesn't change that code tends to be written differently in these two languages. I think the relationship between Python 3 and Python 2 is similar to the relationship between C++ and C in that regard.
The goal that all new Python code will eventually be written in Python 3, I don't think will ever be achieved [1]. Personally I'm not using Python much these days, but when I do use it, I still prefer 2.7
[1]: https://semaphoreci.com/blog/2016/11/11/python-versions-used...
What does Python3 require of you that isn't necessary in Python 2? Print as a function is my only example.
Python 3 lets you continue writing the same same simple stuff as ever. It also provides a bunch of other power that you can _choose_ to use.
The OP's example is such a strawman it's hard to take seriously. If you're writing little scripts (or teaching someone some introductory programming) You don't need to use decorators or type annotations or asnyc/await. If you're Dropbox and you've deployed 4 million + lines of Python, then maybe type annotations make sense for you, and there they are.
What is there about 2.7 that you prefer? The thing that most surprised me after finally moving to python 3 full-time a few years back, was that it was so completely painless.
Choosing Python 2 when I can is like setting in place a simpler coding standard.
Which part of this incoherence are you most fond of?
* The part where he gives an example of "simple" python 2 hello world and pretends that the equivalent python 3 isn't exactly the same thing with two added brackets ( ) ?
* The example he does give instead which isn't even valid python.
* The part at the end where he gets confused between type safety and static typing and declares a preference for C based upon that.
Why? It mystifies me utterly that people think that having the option to do something is a burden. What is it about asyncio just sitting there in the stdlib that you find heinous? I don't use the shelve package either, but I never thought "I need to find a language where I can't easily import this monstrosity".
I don't quite understand. You can easily use Python without knowing asyncio exists. The last time I ever thought about asyncio while programming Python was when I was using asyncio.
Another HN thread on python strings got me thinking about the print() function. This is going to sound a bit trivial but bear with me. Although I agree that print() is more consistent with how functions are called in Python, I can totally see how irritating it would be for a Python 2 programmer. It's also just generally disruptive to typing flow: when you've finished typing the word 'print' your hands are 'out of position', making it a bit jarring to type the open parenthesis.
This has me wondering: is there a language out there where deliberate thought has been put towards typing ergonomics and fluency? And I wonder if such a language would have a material impact on developer productivity?
I found it extremely (to the point of a frustration-induced mental breakdown) hard. I still can't fit it all in my brain, but I got enough so that my code works. The best explanation I can give is by analogy: think of the kernel of an OS, and how it spreads CPU time across all the processes. Sometimes processes know they dont need to work, say they're waiting for a disk read, or a network message, so they surrender and say "ok kernel, I'm done for now, let someone use CPU". Thats like what the "yield" command does in asyncio, although yield requires a context. So you say "yield until this function does something interesting" (I think it's called 'await' now), then a mini-"kernel" (the io service) stops executing that function and polls all the other functions to see if any of their yields have changed state. It just keeps polling till it finds some work it can do. I dont yet fully grok the futures yet, but I think they're just a way of packaging up the "work item" produced when a yield actually gives you something.
* Disclaimer: I barely understand this, so if I'm spreading bad information I apologize in advance.
I have nothing against asyncio in python, I think its presence helps put python in the "big leagues" of languages, and not just a toy for noobs with arduinos. It's an additional language feature, like C++ templates. You dont have to use it, so the noobs can keep doing their thing. But it prevents more experienced devs from outgrowing the language and having to learn a new one, or port working code to a new language.
And I get what you're saying about having nothing against asyncio being in the standard lib: I mostly agree. You can ignore it if you don't like it. And it does allow the more skillful python devs to do pretty amazing things (e.g. sanic, that uvloop pgsql driver etc.). I guess the small niggle I have with asyncio is similar to the one have with the standard library documentation (and Gnome, for that matter): I can't understand what the authors/developers were trying to achieve when writing it.
Take the std lib documentation for instance. It's only my opinion, but there seems to be very little consistency between libraries, and much of the documentation reads like a stream of consciousness punctuated by the occasional "oh and there's this thing too". This makes it very difficult to learn about what is being documented.
I mean, that's fine, it's their project and their prerogative and it isn't all bad. But it just seems self-defeating to write documentation that is incomprehensible. I suppose one could view technical documentation as a work of art that has some kind of intrinsic artistic value... Otherwise it just seems like wasted effort to write documentation that doesn't convey information in a useful way.
Sorry this turned a bit ranty. I'm only speaking for myself here; it's entirely possible I just happen to think in a way that is very different to how the std lib doc authors do.
> I can't understand what the authors/developers were trying to achieve when writing it.
I can't speak for them, but event-driven designs are a great alternative to procedural polling / event loop designs. I am not sure, but I think there's a relationship to the functional programming style where you say "when there's data, do this to it". So I think what they're trying to accomplish is to enable FP paradigms in python. You could write a coroutine that says "yield until there's data, when there is, transform it".
I used it with zeromq [1] to route messages between a few C++ programs that all work together. So my python program is a "supervisor" task that sends heartbeat messages to my binary programs over zeromq. Asyncio is handy for timing the heartbeats (because you can say "in 2 seconds, do this") and reading the message queue. I also hooked it up to inotify, so I can do "echo SOME_COMMAND > command.txt" and as soon as command.txt is written to, my supervisor gets a notification, reads the file, and processes the command. I almost lost my sanity to get it working, but once I got it, I really like it. One tip though, dont try to mix async and sync programming. Go big or stay home.
Now, going down the rabbit hole of "no syntax" in the end one walks by lisp/scheme and end up at lamdba calculus (or brainfuck...).
Smalltalk has very little syntax.
I've been thinking a bit about how simple is is simple enough for useful computer languages, with an emphasis on reading and writing. The Apl people claim dense notation is good, while I think that "pseudo code" should be enough - syntax is for communicating with humans, the machines have machine and byte code.
Other [ed: "real" languages with rather concise syntax] are Julia, Kotlin and Nim.
I find that using whitespace for blocks (or begin/end) is generally preferable to brackets - we generally only use parentheses in prose and poetry - typing []{}<> is invariably a little complicated with interfaces developed for typing text. @ is actually a little easier thanks to the rise of email (addresses).
I'm biased though, as I generally use a Norwegian keyboard layout - making room for the three extra letters "æøå" exiles [{'< somewhat, which in turn pushes the backtick and a few other "easily available" punctuation marks firmly into repetitive stress syndrome territory.
- Python2 seemed to enjoy some success because of its simplicity
- Python3's breaking changes seemed ill thought out. As an example, PEP-414 [1], which reintroduced explicit Unicode string literals to ease porting Python2 to Python3. The fact that it was removed in the first place suggests there was a lack of thought about or concern for the effects of breaking changes. It's almost like once the decision was made to make breaking changes then considerations about porting and libraries maintaining compatibility between the two were of no concern.
- IMHO there has been a shift away from dynamic languages that came at a rather bad time with the schism in Python land.
- Non-backwards compatible changes have often gone badly. Perl5 to Perl6. PHP 6. Python 3. I mean gone badly in the sense that it seemed to hurt adoption, at least for awhile.
- It seems like statically typed languages have somewhat supplanted some of the use cases for these languages. I'm thinking of Go as one specific example. The way I like to put it is that dynamic languages force you to have unit tests for spelling mistakes and typos.
If you compare the Python3 async stuff with Go's I honestly think Go is more elegant here.
- Lastly of course there's the GIL. I think this is increasingly becoming a problem in a multi-core/multi-threaded world.
The GIL design really does simplify writing C extensions. This makes Python pretty convenient and well-suited for certain tasks. I'm thinking specifically of things using Numpy.
Anyway I'm not saying you can't write, say, high-performance Web servers in Python with AsyncIO/gevent loops and the like. It's just not as... elegant and simple as things seemed back in the days when Python 2.7 was state of the art.
>It has what they call gradual typing in that it is dynamic like python, but you can add types to functions that help to catch lots of errors.
Is this something like in Haskell, where I've read (not sure of the details) that you can define types related to the parts of the application or business domain / business logic, which then enables more error-checking by the compiler when you use those types in your code? It may be things like instead of using just an int, if it is meant to represent say height of humans, you might add constraints like height > 0 and height <= 10 feet (because you think or know that no human can be taller than that). Then the compiler will warn you or give an error if you try to assign a value to a height variable, which is outside that range.
Pascal has a version of this feature oo, but maybe Haskell has more support for this stuff - not sure.
Perl-like "unless" (reverse if) feature in Python:
https://jugad2.blogspot.in/2017/02/perl-like-unless-reverse-...
Is this a serious statement?
The beauty of Python is that you can learn it quickly, and then it can take you anywhere you want to go. That is quite the accomplishment, and that is why it is the perfect language for beginners.
I think the authors statement is meant to contrast those properties with node.js, which imho has neither of the, and is also asynchronous by default; something I think makes it unnecessarily difficult for first-language learners to approach.
def hello(name):
print('hello', name)Python 2:
def hello_world(name):
print 'Hello', name
Python 3: def hello_world(name):
print('Hello', name)
> The language, which was once simple and elegant, has become complicated and clumsyPython 3 is just as simple to use as Python 2 (simpler, even due to all the cleanup that happened - just think about the encoding mess in Python 2).
What happened is that new, powerful features got added to Python 3 that solve specific issues that people were having. It's entirely optional to use these, but they make life much easier if you need them.
Async programming is only really applicable to highly concurrent network programming or other applications that spend a lot of time waiting for IO. For everything else it's just unnecessary overhead. It is inherently complicated. In particular, the async/await paradigm is extremely powerful. I first encountered it in C# and immediately fell in love with it, and I'm happy to see major languages like Python and JavaScript adopt it. It makes clear where you hand off control back to the event loop and prevents all sorts of bugs where you'd accidentally block the main thread by invoking blocking IO.
gevent, in comparison, is an ugly workaround that hides all of the complexity behind async programming. By monkey patching all IO libraries to be magically async, it makes it impossible to reason about the execution flow and it's extremely easy to get it wrong. That is an affront to the Zen of Python (Explicit is better than implicit).
Type annotations are just a standardized way to do what large projects were doing anyway - documenting types. By moving it out of the docstrings and formalizing it, it opens the door to strict type checking. The resulting ugliness reflects the difficulty of typing a dynamic language and you only need it if you want strict type. You can write untyped code just fine.
> I'm not even debating the value of type annotations [...] And why do this when there are hundreds of other languages out there that are statically typed?
Do I have to point of the irony?
I am not sure it qualifies as flamebait. The situation may be a bit more nuanced. I first read some of the comments in this thread, then went and read his article, then came back here to read some more comments.
Charles Leifer (per his resume [1]) is a co-creator of readthedocs.org (where the docs for a lot of Python OSS projects are hosted), and of the PeeWee ORM (which I know of and have used a bit).
[1] http://media.charlesleifer.com/blog/documents/resume.pdf
He also writes a lot of (technical) Python posts on his blog. I've read some of them in the past. Unlikely that a person like him would be interested in writing such a post as flamebait.
I'm guessing the post is describing his genuine thoughts / feelings (right or wrong) about Python's evolution of late, even if some of his points may not have been well-thought-out, per what I read from some comments here. I haven't gone into an analysis of what he wrote vs. the comments here, in depth. But I think we should cut him some slack, and not flag the post as flamebait. Just my 2c as a Pythonista and HNer.
I even agree that asyncio is a clusterfuck, but we're free to use Curio (which looks much better), and if you don't like how complicated type annotations make the language, don't use them. I agree that they've been bolted on rather clumsily (having to import the type system feels weird), but it's nowhere near as big a deal as the author makes of it, and I feel the post makes mountains out of molehills.
Python 3 is where the world is moving to, doesn't mean we're all turning async.
Very few applications really require AIO and/or coroutines, and spawning a coroutine for each I/O request is a madness indeed.
Last but not least, such kind of API should be general and minimalistic, the way Erlang does its processes. Or how Plan9 does I/O via general protocol. Unfortunately, Python guys are looking in a wrong direction (is that C#?) for inspirations.
After experiencing static typing with TypeScript I don't really want to go back to dynamic typing.
Javascript's main failing wasn't a lack of static typing it was a lack of type safety (which statically typed C also suffers from). Python didn't suffer from this.
If you tried to convert an invalid string to an integer it won't just try and have a bad guess at what it thought that you meant (C, Perl and JS's default behavior), it would raise an exception instead.
In TypeScript (with a decent editor, like VSCode) you just hover the parameter and you can immediately see what it is.
Sure it is. Fire up the IPython REPL at the point in the code where you're intending to use it and experiment. Not only can you see what it takes, you can see what it does in real time and you can experiment on the results.
>In TypeScript (with a decent editor, like VSCode) you just hover the parameter and you can immediately see what it is.
Well, you can see that it's a string of some kind.
That is the default behavior of Perl?
That is: UTF-8 should be the default encoding, at least let me specify it somewhere.