Why I hate python
I recently wrote a small internal program in python to automate our client’s builds: run everything overnight, collect the output, and generate some rudimentary web pages It wound up being 250 loc for the program, split into about three files; and 500 loc for the tests. I spent about 2-5 days on it, part time. Just enough to give me a feel for what the language is like.
And I don’t like the language. I know that python is supposed to be the cool language, and perl is ugly line noise. And ruby? I don’t know what people have against ruby. But python is so sexy they even use it to teach the Intro to Computer Science course at Harvey Mudd now.
I hate the way formatting structures control flow. I hate that even in XEmacs in python-mode, I was fighting with it to get the right indentation (which means the right semantics). I hate that I can’t define an empty class or method. Several times I started to write a test, realized I wanted to run something first, and left it stubbed out as
def testHTMLLine:
Well, you can’t do that. You need to do:
def testHTMLLine:
pass
At that point I’ll bring my own curly braces.
I hate that it’s dynamic, but not dynamic enough. I had a set of tests, collected into about five test cases. One set of tests was slow (10 seconds) because it actually tested connecting to the CVS server, checking out a project, building it, etc. The rest of the tests finished in under a second. I wanted to define a test suite that contained all the fast tests only, so I could shorten my test-code-test cycles.
Simple and evil solution: enumerate the test cases that are fast. Evil because I have to remember to update the list if I add a new fast test case. So create a suite at module level like this:
fastTests = ["test.TestParseOutputLog", "test.TestDirClass", "test.TestSystem" ]
fastSuite = unittest.TestLoader().loadTestsFromNames( fastTests )
Clever and dynamic solution: enumerate all the tests but remove the slow ones.
# NOTE: not actually python, this DOESN'T WORKfastTests =__thismodule__.Classes.remove( "SlowTest" ) fastSuite = unittest.TestLoader().loadTestsFromNames( fastTests )
I couldn’t figure out how to easily enumerate all the classes in the module I was in. While loading the module, some of the things which get set up eventually (the module object, for example) are not yet available to me. Look, I know it’s possible because the unittest.main() routine knows how to enumerate all the classes which are descended from unittest.TestCase. But it’s not trivial to do. In ruby you could do something like
fastTests = []
ObjectSpace.each_object( Class ) { |x| fastTests << x.to_s if x =~ /^Test/ }
fastTests.delete(”TestSlow”)
where you could filter on name (starts with Test) and file (if necessary), and then remove the slow one. This isn’t about dynamic vs. static languages, it’s about user experience. In C you know you can’t do reflection, and when a unit test framework like cxxtest depends on perl or Python being installed, that’s fine. But because it’s possible in Python — but obscure and ill-documented — it becomes an annoyance.
The documentation is horrible. Over the last ten years my first recourse when looking for API documentation has been my friend Google. The Python documentation, even though it’s all free and available online, seems to be deliberately poorly organized and indexed. What I was hoping for was a quick cheat sheet on how to do a common thing (string interpolation). What I found was proposals to change or extend Python in varying mutually incompatible ways, in order to make it easier to do string interpolation. And this experience was repeated over and over as I dug through the language, library, and ancillary documentation looking for the Python way to do the things I needed.
Finally, Python doesn’t live up to its hype. How can it support functional programming when expression if (as opposed to statement if) was only added as a language feature in version 2.5? Even C has it!
Perhaps I have this all wrong, and Python is the best language EVAH. In the spirit of Strong Opinions, Weakly Held I welcome corrections and arguments in the comments.
Tags: python sucks
June 22nd, 2008 at 12:04 am
Thanks for giving Python a try. No one language is good for everyone and everything. Although I’m a Python afficianado (read “fanboy”), I personally don’t like too much hype because it raises expectations way too high. It’s a programming language, not a panacea.
The indentation thing has burned me a few times recently. It was actually easier to deal with when I was writing simpler programs. It encourages sparseness and readability, but doesn’t guarantee either.
Again, thanks for giving the language a spin. Good luck with whatever you decide on.
Carl T.
June 22nd, 2008 at 2:34 pm
Carl,
You may be the nicest language evangelist I’ve ever met — I just said your language sucks, and you, a self-proclaimed Python fanboy, leave a polite comment thanking me for trying Python!
Part of my frustration was that ActiveState doesn’t extract the Python HTML documentation by default, effectively breaking the online help when you work with the interpreter interactively. Of course, cygwin’s Python installation, that I have installed ON THE SAME MACHINE, does have it installed. So I think it would be fair to call that whining on my part.
June 22nd, 2008 at 3:17 pm
For finding classes in a module you could use module inspect
import optparse
import inspect
inspect.getmembers(optparse, inspect.isclass)
Really, it was just 1 minute of Googling
And for doing the filtering you can use list comprehensions like this:
[m[0] for m in inspect.getmembers(optparse, inspect.isclass) if m[0] not in ['Values']]
In the example ‘Values’ represents the slow test class…
And for the fanboy thing don’t worry, _love_ to a language is something more related to taste and personal preferences.
e.g. I played someday with Ruby and was put off by its likeness to Perl and didn’t quite like blocks and all that other things… maybe Python is better for my way of thinking YMMV
June 22nd, 2008 at 4:39 pm
Thanks for the reply.
I started programming getting VBA, VB6, and eventually VB.net and C# and Java shoved down my throat. I’ve warmed up to C# a little since, but having a commercial hype machine like Microsoft wearing you down can be a real demotivator.
The nice thing about open source is (cliche inbound) choice. If you hate Python, you can use Ruby or Perl. If you are a hard core functional type, there are a handful of free Schemes and Common Lisps.
Trying out the different offerings, even if they fail you, introduces concepts that you can learn from. That shows some initiative. If you’ve written an entire Python program that actually does something, you’ve got a right to gripe and say what you want. So I wasn’t just being nice. I’m cool with do’ers. It’s people talking out their rear ends that chafe me, but that’s a whole ‘nother rant . . .
June 22nd, 2008 at 6:06 pm
@James -
That probably works if you don’t want your code to run at file scope in the module you’re introspecting on. I was getting “NameError: name ‘test’ is not defined”
Now, I guess I could have done something like this–
def stubMainThatCanIntrospect():
# do my introspection
# then call unittest.main()
if __name__ == ‘__main__’:
stubMainThatCanIntrospect()
But that looks like a hack to me.
As you say, YMMV. Everything looks awesome for a professional driver on a closed course.
June 23rd, 2008 at 3:04 pm
Sorry Sam, maybe I didnt’t quite understood your problem.
If you want to know in which module you are (and even import it) from anywhere in the file (inside a function or from main) you can use a nasty code like this.
if __name__==’__main__’:
thismodule = __file__.split(’/')[-1][:-3]
print thismodule
m = __import__(thismodule)
print m
As you see by this code I’m no pro driver, more like a hackery cowboy…
September 16th, 2008 at 7:28 pm
I’ve written a couple of medium-sized programs in Python and quite a few scripts for Blender, and I can´t say I like it. It was nice to see someone else that didn’t immediately swore off all other languages for Python.
I am a C/C++ programmer by heart and can´t say I like script languages in general, but so far Perl has come closest to pleasing me.
My main complaints over Python is the use of whitespace characters for block-level separation. It’s is simply too fragile in my opinion. If you erase a tab while browsing the code, it can make a very hard-to-locate error; esp. since the error reporting capabilities of the Python interpreter isn’t on par with other languages. If you change your editor to display tab characters, you got something even less readable that any language using braces…
For me it boils down to the fact that I don´t find the language robust enough to efficient programming unless I use external code checking utilities. I think it is a very nice beginner’s language, but if you have no fear of C-ish syntax there is little to be gained and a lot to lose with the fluffy-syntax approach.
November 20th, 2008 at 1:25 pm
I agree 100%. Coming from C++, I’ve just been forced to work with Python, and I’ve grown to completely hate it:
* Indentation problems. Try indenting python with tabs. Suddenly you get unknown errors coming from everywhere.
* No forward declarations. So you’re FORCED to have all your functions have that ugly indentation in front of them. It’s like PHP, but worse: No braces.
* pass. Requiring a keyword to allow to define empty functions? Come on!
* I cannot include “thispath/thisfile.py”. No, first I have to add the path to the global import path, and then import it normally. With C++ you can #include whatever file you want.
* if __name__==’__main__’: WTF??
* There’s simply no built-in compiler for python, turning all your compile errors into RUNTIME errors. Therefore you can’t “./configure, make, sudo make install” with python. This means that if your favorite python application isn’t listed in your favorite linux distro’s repository, you need to install the scripts and PRAY that the requirements are already installed.
* Python is a newbie-magnet. Even popular python apps (like Frets on Fire) fail at OBVIOUS usability tests (hello, I pressed escape, why do you keep crashing on me)?
I hate python. I absolutely and irrevocably hate python! Ugh!