So, I'm at Red Hat now :) I'm now a Quality Engineer working on OpenStack which is a new direction for me. This is the first time I have been working on a 100% software project. Well, that's not entirely true I guess. I did spend 18 months designing an automation framework from scratch. Nevertheless, this is new and interesting.
That being said, OpenStack is written almost entirely in Python. Namely Python 2.7. uggh.
Why the moaning? I used to be a big rah-rah python guy. A former co-worker of mine even jokingly wondered if Guido Van Rossum was paying me money to try to switch our company over to Python (which by the way, I pretty much single handedly did). However, over the years, I have come to find many pain points with the language that has considerably dimmed my enjoyment of the language. Now, hopefully I won't get any flames. Python isn't a bad language and it has quite a few interesting features. I just find myself longing for some things python lacks. And indeed, with some really interesting dynamic interpreted (or JIT'ed) system programming languages like Go, Julia, and even Swift, I really wonder how much wind is going to get taken out of Python's sails in the next 5 years? And that doesn't even factor in the non-system's programming languages like Clojure, Elixir or even TypedScript or LiveScript (a haskell-like variant of javascript).
Duck Typing ain't enough
I think Python 3 came to this realization with their new argument annotations, and so Python 3 doesn't suffer from this problem like Python 2 does. Type hinting is the way to go. It allows the developer to rapidly prototype an idea, and then for performance or documentation reasons, type the variables and return code later. It would be nicer if Python was like Julia (or TypedClojure) and allowed even locals to be optionally typed.
When you start getting code bases into the many tens of thousands or more of code, you just look at a function and wonder "ok, what kind of variable am I supposed to pass in?". Some of you may be saying that's what a good docstring is for. I would agree, except that we all know the first thing to bit-rot is documentation.
Moreover, duck-typing can lead to unintended problems. Perhaps you want to pass in an object that supports the method quack(). Unfortunately, the user so happens to pass in a BadDoctor class object, and your function happily calls the quack() method for you.
Hard to make constants (immutables)
Basically, if you want to truly make an immutable object in python, you'll need to subclass from int, tuple, string or some other immutable built in type. And it's a little odd to do so. It's one of the few places that implementing __new__() is required. I often tell people that python's __init__ is not the constructor, __new__ is. It is __new__ that actually allocates the memory for the object, and __init__ initializes the allocated memory. If you have an immutable object, you have to give it a value as soon as it is created.
Another way to make "read-only" objects is to use a setter property. It's not fool-proof, but it does allow one to make a mostly read-only object. You could also reimplement __getattr__ and __setattr__ for the class and have it look up what you are trying to access. And lastly, you could write a C(++) module for the data structure which does have const. But really, would you want to do that?
Performance
Pypy aside, python's performance leaves something to be desired. It also seems that Guido is totally nonplussed by python's performance and thinks it's good enough. I was quite startled to recently learn how good the V8 Javascript engine performs. That's not bad at all, and would make it on average about as fast as PyPy. But Openstack requires regular CPython, mainly because of lots of dependencies on modules that use C modules (when you install OpenStack from devstack or packstack, you'll see some source compilation going on).
The Browser as the new VM
Like it or not, the browser is kind of the new VM. That means that javascript is becoming as important as C or Java and just as ubiquitous. Having an application that can run virtually anywhere, including mobile devices is not to be scoffed at. Also, I was surprised to learn the new tricks HTML 5 has up its sleeve. This includes a File System API so that you can finally read local files (albeit to a sandboxed file system), the websocket API, WebGL, and drag and drop support just to mention a few. Since javascript is the de facto language of the browser, that means for better or worse learning javascript. There are quite a few python-to-javascript libraries out there, including pyjs, and brython. However, they are not developed by the core python team and so I wonder if/when support will end? And brython only supports python3.
No persistent data structures built-in
So there is pysistence. But being a non-standard 3rd party library and with the lack of data-typing, it means that users will not be sure when persistent or non-persistent data types are being used. Why do we want persistent data structures by default? This page and this one sum it up pretty well.
Lack of good concurrency
Python, thanks to the GIL, doesn't really have true concurrency. There is multiprocessing, which fires up a new python interpreter, but it does have some limitations (like the arguments must be pickle-able on Windows) which can be a real pain. Also, since a new python interpreter is getting fired up for each new multiprocess, python developers can't really laugh at the JVM's large consumption of memory once you start firing up 20+ processes. Hopefully pypy will solve this problem with Software Transactional Memory.
That being said, OpenStack is written almost entirely in Python. Namely Python 2.7. uggh.
Why the moaning? I used to be a big rah-rah python guy. A former co-worker of mine even jokingly wondered if Guido Van Rossum was paying me money to try to switch our company over to Python (which by the way, I pretty much single handedly did). However, over the years, I have come to find many pain points with the language that has considerably dimmed my enjoyment of the language. Now, hopefully I won't get any flames. Python isn't a bad language and it has quite a few interesting features. I just find myself longing for some things python lacks. And indeed, with some really interesting dynamic interpreted (or JIT'ed) system programming languages like Go, Julia, and even Swift, I really wonder how much wind is going to get taken out of Python's sails in the next 5 years? And that doesn't even factor in the non-system's programming languages like Clojure, Elixir or even TypedScript or LiveScript (a haskell-like variant of javascript).
Duck Typing ain't enough
I think Python 3 came to this realization with their new argument annotations, and so Python 3 doesn't suffer from this problem like Python 2 does. Type hinting is the way to go. It allows the developer to rapidly prototype an idea, and then for performance or documentation reasons, type the variables and return code later. It would be nicer if Python was like Julia (or TypedClojure) and allowed even locals to be optionally typed.
When you start getting code bases into the many tens of thousands or more of code, you just look at a function and wonder "ok, what kind of variable am I supposed to pass in?". Some of you may be saying that's what a good docstring is for. I would agree, except that we all know the first thing to bit-rot is documentation.
Moreover, duck-typing can lead to unintended problems. Perhaps you want to pass in an object that supports the method quack(). Unfortunately, the user so happens to pass in a BadDoctor class object, and your function happily calls the quack() method for you.
Hard to make constants (immutables)
Basically, if you want to truly make an immutable object in python, you'll need to subclass from int, tuple, string or some other immutable built in type. And it's a little odd to do so. It's one of the few places that implementing __new__() is required. I often tell people that python's __init__ is not the constructor, __new__ is. It is __new__ that actually allocates the memory for the object, and __init__ initializes the allocated memory. If you have an immutable object, you have to give it a value as soon as it is created.
Another way to make "read-only" objects is to use a setter property. It's not fool-proof, but it does allow one to make a mostly read-only object. You could also reimplement __getattr__ and __setattr__ for the class and have it look up what you are trying to access. And lastly, you could write a C(++) module for the data structure which does have const. But really, would you want to do that?
Performance
Pypy aside, python's performance leaves something to be desired. It also seems that Guido is totally nonplussed by python's performance and thinks it's good enough. I was quite startled to recently learn how good the V8 Javascript engine performs. That's not bad at all, and would make it on average about as fast as PyPy. But Openstack requires regular CPython, mainly because of lots of dependencies on modules that use C modules (when you install OpenStack from devstack or packstack, you'll see some source compilation going on).
The Browser as the new VM
Like it or not, the browser is kind of the new VM. That means that javascript is becoming as important as C or Java and just as ubiquitous. Having an application that can run virtually anywhere, including mobile devices is not to be scoffed at. Also, I was surprised to learn the new tricks HTML 5 has up its sleeve. This includes a File System API so that you can finally read local files (albeit to a sandboxed file system), the websocket API, WebGL, and drag and drop support just to mention a few. Since javascript is the de facto language of the browser, that means for better or worse learning javascript. There are quite a few python-to-javascript libraries out there, including pyjs, and brython. However, they are not developed by the core python team and so I wonder if/when support will end? And brython only supports python3.
No persistent data structures built-in
So there is pysistence. But being a non-standard 3rd party library and with the lack of data-typing, it means that users will not be sure when persistent or non-persistent data types are being used. Why do we want persistent data structures by default? This page and this one sum it up pretty well.
Lack of good concurrency
Python, thanks to the GIL, doesn't really have true concurrency. There is multiprocessing, which fires up a new python interpreter, but it does have some limitations (like the arguments must be pickle-able on Windows) which can be a real pain. Also, since a new python interpreter is getting fired up for each new multiprocess, python developers can't really laugh at the JVM's large consumption of memory once you start firing up 20+ processes. Hopefully pypy will solve this problem with Software Transactional Memory.
