There's a lot I like about Python, but there are a couple of things that they've gotten so horribly wrong.
1. The KeyboardInterrupt exception for SIGINT. Whoever came up with that idea destroyed the credibility of the entire interpreter. Python falls flat on its face to me because of this one design choice. It's impossible to write a Python script that will not dump a full debug stack trace if you send SIGINT (ie: Ctrl+C) before the first line of your script is reached. That is, even if your very first line of code is a try/except block intended to catch KeyboardInterrupt, a SIGINT early on will still fail spectacularly at some point during Python's internal startup. Python runs a lot of code before turning control over to your script and it's simply not possible to, from within Python, catch these signals.
In order to provide a professional piece of software to clients that will not dump debugging gibberish to the terminal, one must wrap every single Python script with a shell script or small C binary that catches signals and proxies/rewrites SIGINT as SIGTERM, in order to avoid KeyboardInterrupt entirely. Something as fundamental as signal handling having been botched to this extent is frustrating.
2. The asyncio module. They screwed up the async implementation in the earlier phases, and the hacks that have been implemented in an attempt to improve the situation are grotesque. The state of async in Python is confusing enough as it is, but if you happen to run into one of the edge cases where the ways in which they've hacked the core of the language to make room for the async stuff affects you, you're in for quite the ride.
While it's never been a problem for me, I can see that #1 makes a lot of sense.
% python -c pass
^CTraceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site.py", line 62, in <module>
import os
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 400, in <module>
import UserDict
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/UserDict.py", line 83, in <module>
import _abcoll
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_abcoll.py", line 9, in <module>
"""
KeyboardInterrupt
to avoid importing the site module, then set your signal handlers, then import site manually. In that case the only output, if caught at the wrong time, will be the message 'KeyboardInterrupt'. This isn't quite what you want, but it's a lot closer.
There should be a way to pass an option to Python so that if you do 'python --early-sigint "message"' it prints the message for an early sigint.
You should post that to the python-ideas mailing list. It's a long and tedious process to get everyone on board by writing mails, but it works. Pretty much everyone can do it.
As a minor nitpick it bugs me a lot that there are no truly anonymous functions. You either have to use a lambda which is limited to expressions, or name a function and use it as a first class object. Every other language in the same domain has this feature.
I suppose you could avoid the possibility of a name clash if the interpreter maintained a hidden, name-mangled reference for you...?
Personally I think it's a bigger problem that python isn't all that well suited to functional programming because of lack of tco etc (see slackness python etc). But I understand the design decision.
Python actually does have a kind of "anonymous function" feature, at least in a way that replaces most common use cases. It just happens to be bundled in a unique Python-like way. A lot of people don't seem to know about @contextmanager (contextlib.contextmanager) - it's what provides the functionality for "with" blocks. You've probably seen with() used with file operations (open file, run block of code, file is closed automatically at end of block), but I suspect many developers are unaware that you can create your own context managers.
While they are not true anonymous functions, I have yet to stumble on a scenario where a context manager did not fit the bill. They're easy to create - nothing more than a try/except/finally with a "yield" call to execute... you guessed it, essentially an anonymous function block. It's a little mind-warping the first time through, but it winds up creating clean code. PEP 343 is a good source to learn more.
How do contextmanagers (which by the way, @contextmanager is sugar for manually defining an object with __enter__ and __exit__ methods) take the place of anonymous functions?
1. The KeyboardInterrupt exception for SIGINT. Whoever came up with that idea destroyed the credibility of the entire interpreter. Python falls flat on its face to me because of this one design choice. It's impossible to write a Python script that will not dump a full debug stack trace if you send SIGINT (ie: Ctrl+C) before the first line of your script is reached. That is, even if your very first line of code is a try/except block intended to catch KeyboardInterrupt, a SIGINT early on will still fail spectacularly at some point during Python's internal startup. Python runs a lot of code before turning control over to your script and it's simply not possible to, from within Python, catch these signals.
In order to provide a professional piece of software to clients that will not dump debugging gibberish to the terminal, one must wrap every single Python script with a shell script or small C binary that catches signals and proxies/rewrites SIGINT as SIGTERM, in order to avoid KeyboardInterrupt entirely. Something as fundamental as signal handling having been botched to this extent is frustrating.
2. The asyncio module. They screwed up the async implementation in the earlier phases, and the hacks that have been implemented in an attempt to improve the situation are grotesque. The state of async in Python is confusing enough as it is, but if you happen to run into one of the edge cases where the ways in which they've hacked the core of the language to make room for the async stuff affects you, you're in for quite the ride.