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.
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.
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.
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
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 . . .
@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.
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… 😀
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.
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!
For some unknown reason colleges are pushing Python on their unsuspecting students. If you want quick and easy, I would think some version of BASIC be an easiest path. History majors don’t need the frustration. On the other hand, serious programmers are going go to a compiled language somewhere along the line; why waste time on Python?
I realize this is old news, but I wanted to speak to a few of your issues.
1. If you really want a simpler function, just do: def myfunction(): pass
or def myfunction(): 1 .
2. Regarding your testing issue, and having “fast” and “slow” tests, I have resolved it by using nose (http://somethingaboutorange.com/mrl/projects/nose/) to run the tests. This way, if you have your tests in a class, and define a class variable like “slow” you can call just those tests like this:
$ nosetests somefile.py -a slow
I’m writing a blender script for something like 30 hours now.
:(((((((
My main language is usually C#
I have just typed in google “I HATE PYTHON” so I’m here.
What is blahhh in python.
1. No declaration of variables <– i know i know scrip language , but still sucks (i dont like PHP also)
2. Indents <— this one rely can piss you off in differnt ways.
3. IDE for python after C# in Visual Studio
Rly? Bitching on dynamic programming language for being dynamic, Bitching on language for being not able to customize IDE?
Ok, the article is 1 1/2 years old by now, but as Pyta said, I also googled, but for Why I Hate Python to find out what peeves others had and hopefully how to work around them.
I first tried Python now close to 10 years ago but didn’t like it, coming from a C and Scheme background.
I’ve tried it again every 3 years to see if my peeves had been addressed but still no-show.
Most recently I’ve had to suffer Jython 2.0 in a project and that made me REALLY hate python. Writing in cPython 2.6 isn’t much funnier, but at least scoping isn’t completely broken (referencing outer variables from inner functions) as they used to be.
My main issues are:
9) No standardized packaging system.
easy_install? uninstalling eggs? “go into some dir and remove some files or folders and do some fixups” / “I’ve never found a reason for uninstalling eggs” and idiotic python-cult defenses like that.
8) No natural testing framework.
I use rspec for testing both ruby and java code and it works great. However due to language limitations (closure limits) I can’t see Python being able to support something similar unfortunately.
7) def (fragging_redundant_self):\n self… \n self .. \n self …
But only sometimes… Not needed for inner functions … but let’s annoy you for fist level object functions (90% of all code you write), since we don’t think we’ve caused you enough grief with the tab infinitum puzzle and the underscore contest.
6) No support for anonymous context aware functions (closures). Lambda, hah!
5) Special rules for built-ins. If the language is OO, why can’t I extend or re-define builtins such as {} (dict)? Ok, Ruby is extremely good in this regard and close to perfect for DSLs (sorry about repeating the cliche touted by the ruby fanboys, but it’s mostly true). Javascript is pretty good, not for DSLs but that you know what to expect from the runtime (everything except numbers is a dictionary). You can treat anything as an object and extend even what is typically regarded as native types.
4) Poor documentation !!! Here I think Java and C# shines, Perl is OK, ruby is bad to so-so and Python absolutely stinks in comparison.
3) Giving meaning to indentation. What an idiotic idea in the modern age of personal computing. The only worse language I’ve used in this regard was IBM RPG, but then that language had an excuse of having been created decades before Python when higher level languages started taking off. Didn’t Guido ever write a make-file before he created Python? If so, it seems he learned nothing from that lesson.
2) The Python community. I don’t think you can find a more elitist unhelpful bunch of ass-wipes on the internet (in general.. article author and Carl T. excluded). The attitude hasn’t changed in 10 years so judging by that trend, I don’t hold by breath for the future.
1) Getting Python shoved down my throat by commercial vendors.
When I code Python it feels like 40% of all characters I type are just waste of space, obscuring intent or forcing me to repeat myself without improving readability one iota. Yes, I include indentation in that fraction.
Every time I write some python code or read some piece of code on the net, I get a tinge of bad taste. The code I’ve seen is not more readable than the same algorithms implemented in comparable languages and neither do they communicate intent very clearly.
Are the methods private or not? will I break something or risk my code breaking after an update if I make use of the underscore variants? __is_it__ just the designers idea of moving seldom used functions to the __back__?
To give future readers something to ponder..
Let’s say I want to print out the frequency of words from a column in a space delimited table. In Python I could use this routine:
hash = {}
[hash.update({a:(hash.get(a) or 0)+1}) for a in [re.split(“\s+”,line)[1] for line in open(“file.txt”)] ]
print “\n”.join([ “: “.join([a,str(n)]) for a,n in sorted(hash.items(),lambda i1,i2: cmp(i2[1],i1[1])) ])
And the equivalent in Ruby:
puts open(“file.txt”).map{|line| line.split(/\s+/)[1] }.reduce({}){|hash,a| hash[a] ||= 0; hash[a]+=1; hash}.sort{|i1,i2| i2[1] i1[1]}.map{|a,n| [a,n].join “: “}
This example avoided the abundant tabs which typically plague python code.
Point is, which is more readable? Ok, neither are good examples of readability, but they show some aspects about the language syntax philosophies.
Since ruby allows for easy chaining a’la jQuery it typically leads to less nesting and keeping the problem focused. Each step is clearly delimited, here with curly braces. An editor will help with block highlighting since virtually all editors support brace matching and many do folding as well,
The python example however shows limitations when it comes to chaining which forces me to use a lot more temporary objects (name space and stack clutter) and to break expressions whether *I* want to or not.
Finally, what I don’t understand is why Python has gotten so much traction in the commercial market. Companies selling scriptable tools and middleware typically select Python as their scripting language for their products and I can’t for the life of me understand why. There is nothing simple or readable about Python that can not be expressed better in Javascript or Ruby for example..
That’s my take on why I think Python is as fun as having a live one around the neck.
I’m gonna make a very petty remark about Python. Recently I have been doing symbolic math in Lisp. Lisp was designed for symbolic manipulation and is the reason the whole AI movement got started. Well… it turns out Python has a package for that (SymPy .. a cute little name). So instead of people learning a real language that will truly teach people about symbolic manipulation through programming, Python once again steals the thunder by offering a substitute (poor at best). So newbies are now inclined to go to Python and will have missed out on the learning experience they would have gotten from a language like Lisp. To summarize what I hate … it just seems like Python’s army of programmers are trying so hard to make python into a ‘panacea’ programming language. Pythons abundance of libraries and packages remind of the poor manufactured substitutes coming out of China. Python is like Wal-Mart of programming languages.
Sam,
hello 5 years old thread, disclaimer I’m a python fanboy.
for the Test filter thing:
import inspect
tests = [v for (k,v) in globals().items() if k.startswith(“Test”) and inspect.isclass(v)]
I don’t know Ruby but it doesn’t look very different.
for the function definition, you can write it in one line:
def asdf():pass
will work.
for the docs,
what you are actually needed in my opinion was in the first few chapters of the ‘library reference’ docs – specifically it’s in ‘built-in types’ ‘sequence types’ ‘string formatting operations’:
http://docs.python.org/2.7/library/index.html
http://docs.python.org/2.7/library/stdtypes.html#string-formatting-operations
I don’t know why search engines index it a strange way but I had the same experience with java versions.
its 3rd link of the docs (2.x) main page. after what’s new and tutorial, the 3rd one is ‘library reference’.
strings are among the sequence types, which I think is not very good for ctrl+f-ing string, but in case you skim through the first chapters you will see that the whole thing is indexed in a first-things-first manner.
btw. I know this feeling, myself get it when next-language is not like my-fav-language. I think any language can be frustratingly different. that said maybe python is over-hyped. I agree with you that self-reflecting the module is not one of the strongest points.
well thanks for sharing 🙂 always good to read why others hate what I like.
Naxa,
Thanks for the constructive comments. I haven’t been back to python for a while, but when I do go back I’ll keep your comments in mind.