The amount of time saved by using Python as opposed to something like Java is inversely proportional to the number of people working on the project.

As a programmer in a team, you need rules.  You need structure.  You need order.  Freewheeling your way around a software project is going to create more problems than it solves.

What I'm butthurting about here is Python's duck typing.  It's cute when you're a lone wolf working on a simple Django application, but add a few more people to the project and it quickly becomes unmanageable.  Why?  Because with duck typing, you need to keep a lot more state in your head to interact with other peoples' code.

Pydev for Eclipse Sucks Too

Method signatures are virtually useless in Python.  In Java, static typing makes the method signature into a recipe: it's all the shit you need to make this method work. Not so in Python.  Here, a method signature will only tell you one thing: how many arguments you need to make it work.  Sometimes, it won't even do that, if you start fucking around with **kwargs.

Calling a colleague's method isn't as easy as looking at the signature.  You need to look at the method definition itself to see what it does with its input.

Let's look at an example from Thrift, Facebook's open source RPC server.  Here's the signature to a TServer constructor in Java:

protected TServer(TProcessorFactory processorFactory, TServerTransport serverTransport)
And there are a few other constructors that take different args.  Pretty straight forward, if you look at this, you know what you need to instantiate to get your TServer up and running.  Now let's look at the Python version:

def __init__(self, *args):
So, how do you use it?  Big fuckin' mystery!  You can't overload constructors in Python, so they had to mash the several different constructors into one.  To figure out how to instantiate a TServer, you need to look at the constructor implementation.  As a user of the library, the implementation is none of my concern, unless I'm programming in Python.

What a waste of time.

Whatever You Do, Don't Do It Wrong

What about errors?  Python exceptions are what really make me nervous.  Your code can run fine for the longest time then shit out with a runtime exception.  How do you know what exceptions a method can throw?  Well, you don't, unless you look at the method definition.  Fantastic.

Java has a well thought out hierarchy of checked and runtime exceptions.  Sure, handling checked exceptions means you need to write a bit more code, but it's better to spend the time in development than in debugging at 4am. 

Another example is in order.  In Java, the constructor to FileInputStream throws a FileNotFoundException if something goes wrong.  Since it's a checked exception, you need to deal with it somehow.  The fact that this exception is thrown is made obvious in the documentation, and your code won't compile if you ignore it.

Python, on the other hand, prefers to leave things up to chance.  This is the documentation for the open() builtin, that opens a file:

Help on built-in function open in module __builtin__:

    open(name[, mode[, buffering]]) -> file object
    Open a file using the file() type, returns a file object.
How does this function handle a failure?  Does it raise an Exception?  Does it return a special value?  Nobody seems to know!  Ah, fuck it, that's a runtime problem, right?

Sure, runtime exceptions happen in Java, but they are usually things that are indicative of a big fuckup like a NullPointerException, not something stupid like a file not being found.

Programming a large project in Python makes me uneasy.  Perhaps I'm just doing it wrong?  Do other Pythonistas drop a Valium before they begin the day?