Question

My background is C and C++. I like Python a lot, but there's one aspect of it (and other interpreted languages I guess) that is really hard to work with when you're used to compiled languages.

When I've written something in Python and come to the point where I can run it, there's still no guarantee that no language-specific errors remain. For me that means that I can't rely solely on my runtime defense (rigorous testing of input, asserts etc.) to avoid crashes, because in 6 months when some otherwise nice code finally gets run, it might crack due to some stupid typo.

Clearly a system should be tested enough to make sure all code has been run, but most of the time I use Python for in-house scripts and small tools, which ofcourse never gets the QA attention they need. Also, some code is so simple that (if your background is C/C++) you know it will work fine as long as it compiles (e.g. getter-methods inside classes, usually a simple return of a member variable).

So, my question is the obvious - is there any way (with a special tool or something) I can make sure all the code in my Python script will "compile" and run?

Was it helpful?

Solution

Look at PyChecker and PyLint.

Here's example output from pylint, resulting from the trivial program:

print a

As you can see, it detects the undefined variable, which py_compile won't (deliberately).

in foo.py:

************* Module foo
C:  1: Black listed name "foo"
C:  1: Missing docstring
E:  1: Undefined variable 'a'


...

|error      |1      |1        |=          |

Trivial example of why tests aren't good enough, even if they cover "every line":

bar = "Foo"
foo = "Bar"
def baz(X):
    return bar if X else fo0

print baz(input("True or False: "))

EDIT: PyChecker handles the ternary for me:

Processing ternary...
True or False: True
Foo

Warnings...

ternary.py:6: No global (fo0) found
ternary.py:8: Using input() is a security problem, consider using raw_input()

OTHER TIPS

Others have mentioned tools like PyLint which are pretty good, but the long and the short of it is that it's simply not possible to do 100%. In fact, you might not even want to do it. Part of the benefit to Python's dynamicity is that you can do crazy things like insert names into the local scope through a dictionary access.

What it comes down to is that if you want a way to catch type errors at compile time, you shouldn't use Python. A language choice always involves a set of trade-offs. If you choose Python over C, just be aware that you're trading a strong type system for faster development, better string manipulation, etc.

I think what you are looking for is code test line coverage. You want to add tests to your script that will make sure all of your lines of code, or as many as you have time to, get tested. Testing is a great deal of work, but if you want the kind of assurance you are asking for, there is no free lunch, sorry :( .

If you are using Eclipse with Pydev as an IDE, it can flag many typos for you with red squigglies immediately, and has Pylint integration too. For example:

foo = 5
print food

will be flagged as "Undefined variable: food". Of course this is not always accurate (perhaps food was defined earlier using setattr or other exotic techniques), but it works well most of the time.

In general, you can only statically analyze your code to the extent that your code is actually static; the more dynamic your code is, the more you really do need automated testing.

Your code actually gets compiled when you run it, the Python runtime will complain if there is a syntax error in the code. Compared to statically compiled languages like C/C++ or Java, it does not check whether variable names and types are correct – for that you need to actually run the code (e.g. with automated tests).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top