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?
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()
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).
Related
A lot of the languages I know of (like C++, C, Rust, etc.) print multiple error messages at a time. Then why does python print only one error message?
First off, I assume we are talking about syntax errors, i.e. those that can (and should) be detected and reported by the compiler.
It is primarily a design choice. Python is basically built on the notion that everything should be done during runtime. And the compiler is deliberately kept as simple as possible.
Simple and easy to understand, or complex and sophisticated:
Simply put, you have a choice between either using a very simple compiler that is easy to understand and maintain, or you have a complex piece of machinery with sophisticated program analysis and optimisations.
Languages like C, C++, and Rust take their strength from heavily optimising code during compilationg and thus took the second route with highly complex and extremely sophisticated compilers. Dealing with syntax errors is rather one of their less impressive feats.
Python, on the other hand, went to other way. Indeed, in general, it is quite impossible for a Python compiler to predict what exacty a piece of Python code is doing without actually running it—which precludes all the interesting opportunities for optimisation in the first place, and hence a sophisticated compiler would not really make sense, anyway. Keeping Python's compiler simple and rather focus on runtime optimisations is thus the right choice. But it comes with the downside that the compiler simply bails out whenever it discovers an error.
To give a bit more context...
1. Error Recovery
Dealing with errors and recover from a syntax error in a compiler is hard.
Compilers are usually very good at translating (syntactically) correct programs fast and efficiently to machine code that represents the original program. However, if there is a syntax error, it is often impossible for the compiler to guess the original intention of the programmer, and it is therefore not clear what to do with an erroneous piece of code.
Here is a very simple example:
pen color("red")
Obviously, there is something wrong here, but without further context it is impossible to tell, whether the original intent of this line was pen = color("red"), pencolor("red"), pen.color("red") or something else entirely.
If a compiler wants to continue with looking at the rest of the program (and thus discover potentially more syntax errors), it needs a stretegy of how to cope with such situations and recover so as to move on: it needs an error recovery strategy. This might something as simple as just skipping the entire line or individual tokens, but there is no clear-cut "correct" solution to this.
2. Python's Compiler
Python compiles your program one symbol at a time.
Python's current compiler works by looking at one symbol at a time (called a LL(1) compiler). This makes it extremely simple to automatically build the compiler for Python, and it is quite fast and efficient. But it means that there are situations where, despite an "obvious" syntax error, Python happily moves on compiling the program until it is really lost.
Take a look at this example:
x = foo(
y = bar()
if x > y:
As humans, we quickly see the missing closing parenthesis in line 1. However, from the compiler's perspective, this looks rather like a call with a named argument, something like this:
x = foo(y = bar() if x > y else 0)
Accordingly, Python will only notice that something is wrong when it hits the colon in line 3—the first symbol that does not work with its "assumption". But at that point, it is extremely hard to figure out what to do with this piece of code, and how to correctly recover: do you just skip the colon in this case? Or should you go back and correct something earlier on—and if so, how far back are you going?
3. Follow-up Errors
Error recovery can create "ghost" errors.
In the first example above, the compiler could just skip the entire line and move on without any issue. But there are situations, where the choice of how to recover from a syntax errors influences (potentially) everything that follows, as in this example:
deffoo(x):
The intent behind this could either be def foo(x): or simply a call deffoo(x). But this distinction determines how the compiler will look at the code that follows, and either report an indentation error, or perhaps a return outside a function, etc.
The danger of error recovery is that the compiler's guess might actually be wrong, which could lead to a whole series of reported follow-up errors—which might not even be true errors, but rather ghosts created by the compiler's wrong decision.
Bottom-line: getting error recovery and error reporting right is extremely hard. Python's choice to only report the first syntax error it encounters is thus sensible and works for most users and situations just fine.
I have actually written a parser with more sophisticated error detection, which can list all errors it discovers in a Python program. But to my experience, too many of the additional errors beyond the first one are just rubbish, and I therefore always stuck to displaying only the first error in a program.
Difficult to answer the exact why. I cannot look into the head of the developers of the C-python, jython, pypy or others.
Many errors will only be seen at run time as python is an interpreted language without strict typing.
However each file is compiled to byte code if there is no syntax error.
So for syntax errors I cannot give you the reason, as it should have been technically possible. However I never had issues with this as I use tools like pylint or flake8 to check the code for me.
These tools can detect multiple errors and give a lot of warnings about coding style as well.
So I cannot tell you the why, but only what to do to get multiple errors in one go.
These tools can be configured to just display certain kinds of errors.
to install one or the other tool, just type:
pip install flake8 or pip install pylint
Then type just flake8 or pylint in the directory where all your code is located
or type flake8 <filename> or pylint <filename> to check just one file.
Please note, that many IDEs like for example Microsoft Visual Studio Code, Pycharm, and others can be configured to run these tools automatically for you and signal any issues even before you execute your code.
C or C++ are use compiler to compiled and then execute but python is an interpreted language it means that the interpreter read each line and then execute it when the interpreter see error in on line of program it stopped and display the error in other interpreted language like JS it is the same.
I hope your problem solved but if you want to read more you can google "Interpreted and compiled languages" or see this
When I try to view the built-in function all() in PyCharm, I could just see "pass" in the function body. How to view the actual implementation so that I could know what exactly the built-in function is doing?
def all(*args, **kwargs): # real signature unknown
"""
Return True if bool(x) is True for all values x in the iterable.
If the iterable is empty, return True.
"""
pass
Assuming you’re using the usual CPython interpreter, all is a builtin function object, which just has a pointer to a compiled function statically linked into the interpreter (or libpython). Showing you the x86_64 machine code at that address probably wouldn’t be very useful to the vast majority of people.
Try running your code in PyPy instead of CPython. Many things that are builtins in CPython are plain old Python code in PyPy.1 Of course that isn’t always an option (e.g., PyPy doesn’t support 3.7 features yet, there are a few third-party extension modules that are still way too slow to use, it’s harder to build yourself if you’re on some uncommon platform…), so let’s go back to CPython.
The actual C source for that function isn’t too hard to find online. It’s in bltinmodule.c. But, unlike the source code to the Python modules in your standard library, you probably don’t have these files around. Even if you do have them, the only way to connect the binary to the source is through debugging output emitted when you compiled CPython from that source, which you probably didn’t do. But if you’re thinking that sounds like a great idea—it is. Build CPython yourself (you may want a Py_DEBUG build), and then you can just run it in your C source debugger/IDE and it can handle all the clumsy bits.
But if that sounds more scary than helpful, even though you can read basic C code and would like to find it…
How did I know where to find that code on GitHub? Well, I know where the repo is; I know the basic organization of the source into Python, Objects, Modules, etc.; I know how module names usually map to C source file names; I know that builtins is special in a few ways…
That’s all pretty simple stuff. Couldn’t you just program all that knowledge into a script, which you could then build a PyCharm plugin out of?
You can do the first 50% or so in a quick evening hack, and such things litter the shores of GitHub. But actually doing it right requires handling a ton of special cases, parsing some ugly C code, etc. And for anyone capable of writing such a thing, it’s easier to just lldb Python than to write it.
1. Also, even the things that are builtins are written in a mix of Python and a Python subset called RPython, which you might find easier to understand than C—then again, it’s often even harder to find that source, and the multiple levels that all look like Python can be hard to keep straight.
I use IPython Notebooks extensively in my research. I find them to be a wonderful tool.
However, on more than one occasion, I have been bitten by subtle bugs stemming from variable scope. For example, I will be doing some exploratory analysis:
foo = 1
bar = 2
foo + bar
And I decide that foo + bar is a useful algorithm for my purposes, so I encapsulate it in a function to make it easier to apply to a wider range of inputs:
def the_function(foo, bar):
return foo + bar
Inevitably, somewhere down the line, after building a workflow from the ground up, I will have a typo somewhere (e.g. def the_function(fooo, bar):) that causes a global variable to be used (and/or modified) in a function call. This causes unseen side effects and leads to spurious results. But because it typically returns a result, it can be difficult to find where the problem actually occurs.
Now, I recognize that this behavior is a feature, which I deliberately use often (for convenience, or for necessity i.e. function closures or decorators). But as I keep running into bugs, I'm thinking I need a better strategy for avoiding such problems (current strategy = "be careful").
For example, one strategy might be to always prepend '_' to local variable names. But I'm curious if there are not other strategies - even "pythonic" strategies, or community encouraged strategies.
I know that python 2.x differs in some regards to python 3.x in scoping - I use python 3.x.
Also, strategies should consider the interactive nature of scientific computing, as would be used in an IPython Notebook venue.
Thoughts?
EDIT: To be more specific, I am looking for IPython Notebook strategies.
I was tempted to flag this question as too broad, but perhaps the following will help you.
When you decide to wrap some useful code in a function, write some tests. If you think the code is useful, you must have used it with some examples. Write the test first lest you 'forget'.
My personal policy for a library module is to run the test in an if __name__
== '__main__': statement, whether the test code is in the same file or a different file. I also execute the file to run the tests multiple times during a programming session, after every small unit of change (trivial in Idle or similar IDE).
Use a code checker program, which will catch some typo-based errors. "'fooo' set but never used".
Keep track of the particular kinds of errors you make, analyze them and think about personal countermeasures, or at least learn to recognize the symptoms.
Looking at your example, when you do write a function, don't use the same names for both global objects and parameters. In your example, delete or change the global 'foo' and 'bar' or use something else for parameter names.
I would suggest that you separate your concerns. For your exploratory analysis, write your code in the iPython notebook, but when you've decided that there are some functions that are useful, instead, open up an editor and put your functions into a python file which you can then import.
You can use iPython magics to auto reload things you've imported. So once you've tested them in iPython, you can simply copy them to your module. This way, the scope of your functions is isolated from your notebook. An additional advantage is that when you're ready to run things in a headless environment, you already have your entire codebase in one place.
In the end, I made my own solution to the problem. It builds on both answers given so far.
You can find my solution, which is a cell magic extension, on github: https://github.com/brazilbean/modulemagic
In brief, this extension gives you the ability to create %%module cells in the notebook. These cells are saved as a file and imported back into your session. It effectively accomplishes what #shadanan had suggested, but allows you to keep all your work in the same place (convenient, and in line with the Notebook philosophy of providing code and results in the same place).
Because the import process sandboxes the code, it solves all of the scope shadowing errors that motivated my original question. It also involves little to no overhead to use - no renaming of variables, having other editors open, etc.
If your scripting language of choice doesn't have something like Perl's strict mode, how are you catching typos? Are you unit testing everything? Every constructor, every method? Is this the only way to go about it?
Really-thorough unit tests are the most important technique (yes, I do always aim for 100% coverage), as they also catch many other typos (e.g. where I write + and meant -), off-by-one issues, etc. Integration and load tests exercising every feature are the second line of defense against all kinds of errors (mostly, though, deeper and harder ones;-).
Next are tools such as pylint and pychecker and colorizing editors (I don't use real IDEs, but they would also help similarly to how my trusty gvim editor does;-).
Techniques such as mandatory code reviews (e.g., cfr a video of an interview of mine on the subject here), while crucial, should focus on other issues -- issues that automated tools just won't catch, such as completeness and correctness of comments/docstrings, choice of good/speedy algorithms, and the like (see here for a summary of the talk I gave on the subject at the same conference as I got that interview at, and a link to the slides' PDF).
There are errors other than "typos". If you don't test something, knowing that something's found misspelled variable names won't assure you of much anyway.
Some editors (for example, NetBeans) analyse your code and underline "suspicious" parts, for example unused variables, which may be sign of a typo. NB also highlights the identifier above the cursor elsewhere on the screen, which also helps.
Of course, no clever IDE trick can replace proper testing.
In ruby, a misspelled local variable would cause the program to die horribly, which is fine.
A misspelled instance variable doesn't cause the program to die horribly, which is bad. To detect such cases, use warnings. Unfortunately, you can't easily tell ruby to treat warnings as errors.
TDD -- write your tests first, then the simplest code to pass the test. That way you can be more sure that you don't have any untested code. This will help make sure you have fewer typos or other errors in your code.
Pair programming/code reviews -- two pairs of eyes are better than one pair.
IDE with intellisense -- not a panacea, but a great help in not making typos. If you use intellisense, you typically get substitution errors, not typos. These shouldn't be hard to find with tests.
In my case, I use unit testing extensively (developing in Python). Because there are many lightweight testing frameworks well integrated into the language (or IDE if you prefer), using them cause you almost no pain ;)
Look at this example:
def unpack_args(func):
def deco_func(*args):
if isinstance(args, tuple):
args = args[0]
return func(*args)
return deco_func
def func1(*args):
"""
>>> func1(1,2,3)
(1, 2, 3)
>>> func1(*func2(1,2,3))
(1, 2, 3)
>>> func1(func2(1,2,3))
((1, 2, 3),)
"""
return args
def func2(*args):
"""
>>> func2(1,2,3)
(1, 2, 3)
"""
return args
#unpack_args
def func3(*args):
return args
def test():
"""
>>> func3(func2(1,2,3))
(1, 2, 3)
"""
import doctest
doctest.testmod(verbose=True)
test()
-----------------------------
Results:
Trying:
func1(1,2,3)
Expecting:
(1, 2, 3)
ok
Trying:
func1(*func2(1,2,3))
Expecting:
(1, 2, 3)
ok
Trying:
func1(func2(1,2,3))
Expecting:
((1, 2, 3),)
ok
Trying:
func2(1,2,3)
Expecting:
(1, 2, 3)
ok
Trying:
func3(func2(1,2,3))
Expecting:
(1, 2, 3)
ok
3 items had no tests:
__main__
__main__.func3
__main__.unpack_args
3 items passed all tests:
3 tests in __main__.func1
1 tests in __main__.func2
1 tests in __main__.test
5 tests in 6 items.
5 passed and 0 failed.
Test passed.
I presume by 'typo' you mean mistyping variable/function/class names. This is less of an issue in Python than in Perl, since Perl (and I believe Ruby) by default will automatically create a variable and initialise it to zero or "" on its first use. Python does not do this since it is an error to use a variable that has not been explicitly created, so in that sense it is already in 'strict' mode.
I use Vim with the pyflakes plugin, which underlines most kinds of typos as soon as you type them. I also use pylint and pychecker frequently since they can catch many other kinds of errors.
Another thing I do is make heavy use of Vim's auto completion - I only type a name in full once, then on subsequent uses of the name type the first few letters and use <ctrl-n> or <ctrl-p> to cycle through the matches.
I also use Test Driven Development with the aim of 100% unit test coverage.
I find that the combination of all these practices means that problems caused by typos are virtually non-existent.
Many unit test tools can show the percentage of lines they tested. The closer this percentage is to 100% the less likely variable name typo was done.
In Groovy, the abstract syntax tree (AST) that makes up a program is readily available. So tools can be written that inspect the AST and issue warnings for things that are probably errors.
For example, GroovyLint will warn you if you try to call a method that doesn't exist at compile-time, but is very close to one that does exist.
Example:
class Test{
static def foobar(){ return 5; }
}
Test.fooBar() //Here GroovyLint suggests calling foobar instead of fooBar.
I write all my Python code in eclipse IDE. As Mladen Jablanović has suggested, eclipse underlines suspicious parts.
Next step is to run the code. Now there are two kinds of errors that I am likely to face.
Errors that the interpreter catches and gives me a line number for: These are typically quite easy to debug, especially if you print all the variables in that line just before that line, to make sure that they contain the values that you'd expect.
Unexpected behavior: your code is fine and the interpreter doesn't complain, but your code doesn't behave the way you want it to. When this happens (rarely, because I usually design my modules quite well - a process that takes about 7 minutes - before I start coding) I start looking at modules/functions in the order in which they are called and try to execute the program in my head as the interpreter would see it. If that doesn't work, then I go on to explore the debugger. Usually, it doesn't come down to this, but if it does, it's a pretty big bug and it would take quite some time to fix. Unit tests help, but frankly, I think that as a computer scientist, I should be able to debug it from an algorithms analysis perspective, which is generally faster than unit testing (at least for me). Plus, choosing to do an algorithms analysis over unit testing exercises my brain so that I don't make such mistakes in the future, as opposed to unit testing which helps me fix the problem now, but doesn't do much in terms of helping me avoid making the same/similar mistake in the future.
Hope this helps
I am basically from the world of C language programming, now delving into the world of scripting languages like Ruby and Python.
I am wondering how to do debugging.
At present the steps I follow is,
I complete a large script,
Comment everything but the portion I
want to check
Execute the script
Though it works, I am not able to debug like how I would do in, say, a VC++ environment or something like that.
My question is, is there any better way of debugging?
Note: I guess it may be a repeated question, if so, please point me to the answer.
Your sequence seems entirely backwards to me. Here's how I do it:
I write a test for the functionality I want.
I start writing the script, executing bits and verifying test results.
I review what I'd done to document and publish.
Specifically, I execute before I complete. It's way too late by then.
There are debuggers, of course, but with good tests and good design, I've almost never needed one.
Here's a screencast on ruby debugging with ruby-debug.
Seems like the problem here is that your environment (Visual Studio) doesn't support these languages, not that these languages don't support debuggers in general.
Perl, Python, and Ruby all have fully-featured debuggers; you can find other IDEs that help you, too. For Ruby, there's RubyMine; for Perl, there's Komodo. And that's just off the top of my head.
There is a nice gentle introduction to the Python debugger here
If you're working with Python then you can find a list of debugging tools here to which I just want to add Eclipse with the Pydev extension, which makes working with breakpoints etc. also very simple.
My question is, is there any better way of debugging?"
Yes.
Your approach, "1. I complete a large script, 2. Comment everything but the portion I want to check, 3. Execute the script" is not really the best way to write any software in any language (sorry, but that's the truth.)
Do not write a large anything. Ever.
Do this.
Decompose your problem into classes of objects.
For each class, write the class by
2a. Outline the class, focus on the external interface, not the implementation details.
2b. Write tests to prove that interface works.
2c. Run the tests. They'll fail, since you only outlined the class.
2d. Fix the class until it passes the test.
2e. At some points, you'll realize your class designs aren't optimal. Refactor your design, assuring your tests still pass.
Now, write your final script. It should be short. All the classes have already been tested.
3a. Outline the script. Indeed, you can usually write the script.
3b. Write some test cases that prove the script works.
3c. Runt the tests. They may pass. You're done.
3d. If the tests don't pass, fix things until they do.
Write many small things. It works out much better in the long run that writing a large thing and commenting parts of it out.
Script languages have no differences compared with other languages in the sense that you still have to break your problems into manageable pieces -- that is, functions. So, instead of testing the whole script after finishing the whole script, I prefer to test those small functions before integrating them. TDD always helps.
There's a SO question on Ruby IDEs here - and searching for "ruby IDE" offers more.
I complete a large script
That's what caught my eye: "complete", to me, means "done", "finished", "released". Whether or not you write tests before writing the functions that pass them, or whether or not you write tests at all (and I recommend that you do) you should not be writing code that can't be run (which is a test in itself) until it's become large. Ruby and Python offer a multitude of ways to write small, individually-testable (or executable) pieces of code, so that you don't have to wait for (?) days before you can run the thing.
I'm building a (Ruby) database translation/transformation script at the moment - it's up to about 1000 lines and still not done. I seldom go more than 5 minutes without running it, or at least running the part on which I'm working. When it breaks (I'm not perfect, it breaks a lot ;-p) I know where the problem must be - in the code I wrote in the last 5 minutes. Progress is pretty fast.
I'm not asserting that IDEs/debuggers have no place: some problems don't surface until a large body of code is released: it can be really useful on occasion to drop the whole thing into a debugging environment to find out what is going on. When third-party libraries and frameworks are involved it can be extremely useful to debug into their code to locate problems (which are usually - but not always - related to faulty understanding of the library function).
You can debug your Python scripts using the included pdb module. If you want a visual debugger, you can download winpdb - don't be put off by that "win" prefix, winpdb is cross-platform.
The debugging method you described is perfect for a static language like C++, but given that the language is so different, the coding methods are similarly different. One of the big very important things in a dynamic language such as Python or Ruby is the interactive toplevel (what you get by typing, say python on the command line). This means that running a part of your program is very easy.
Even if you've written a large program before testing (which is a bad idea), it is hopefully separated into many functions. So, open up your interactive toplevel, do an import thing (for whatever thing happens to be) and then you can easily start testing your functions one by one, just calling them on the toplevel.
Of course, for a more mature project, you probably want to write out an actual test suite, and most languages have a method to do that (in Python, this is doctest and nose, don't know about other languages). At first, though, when you're writing something not particularly formal, just remember a few simple rules of debugging dynamic languages:
Start small. Don't write large programs and test them. Test each function as you write it, at least cursorily.
Use the toplevel. Running small pieces of code in a language like Python is extremely lightweight: fire up the toplevel and run it. Compare with writing a complete program and the compile-running it in, say, C++. Use that fact that you can quickly change the correctness of any function.
Debuggers are handy. But often, so are print statements. If you're only running a single function, debugging with print statements isn't that inconvenient, and also frees you from dragging along an IDE.
There's a lot of good advice here, i recommend going through some best practices:
http://github.com/edgecase/ruby_koans
http://blog.rubybestpractices.com/
http://on-ruby.blogspot.com/2009/01/ruby-best-practices-mini-interview-2.html
(and read Greg Brown's book, it's superb)
You talk about large scripts. A lot of my workflow is working out logic in irb or the python shell, then capturing them into a cascade of small, single-task focused methods, with appropriate tests (not 100% coverage, more focus on edge and corner cases).
http://binstock.blogspot.com/2008/04/perfecting-oos-small-classes-and-short.html