Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a need for a "use strict" Python compiler?

There exist static analysis tools for Python, but compile time checks tend to be diametrically opposed to the run-time binding philosophy that Python embraces. It's possible to wrap the standard Python interpreter with a static analysis tool to enforce some "use strict"-like constraints, but we don't see any widespread adoption of such a thing.

Is there something about Python that makes "use strict" behavior unnecessary or especially undesirable?

Alternatively, is the "use strict" behavior unnecessary in Perl, despite its widespread adoption?

Note: By "necessary" I mean "practically necessary", not strictly necessary. Obviously you can write Perl without "use strict," but (from what I've seen) most Perl programmers do use it.

Note: The Python interpreter-wrapper need not require "use strict"-like constraints -- you could use a pseudo-pragma similar to "use strict" that would be ignored by the normal interpreter. I'm not talking about adding a language-level feature.


Update: Explaining what "use strict" does in Perl per comments. (Link to official docs is in the first paragraph.)

The "use strict" directive has three distinct components, only two of which are really interesting:

  • use strict vars: Statically checks lexically scoped variable usage in your program. (Keep in mind that, in Python, there is basically only global scope and local scope). Many Python linters check for this sort of thing. Since it's the only static analysis that they can do, the linters assume you use straightforward lexical scoping and warn you about things that appear wrong in that sense until you tell them to shut up; i.e.

    FOO = 12 foo += 3 

    If you're not doing anything fancy with your namespaces this can be useful to check for typos.

  • use strict refs: Prevents symbolic namespace dereferencing. Python's closest analog is using locals() and globals() to do symbolic binding and identifier lookup.

  • use strict subs: No real analog in Python.

like image 327
cdleary Avatar asked Mar 05 '09 02:03

cdleary


People also ask

Is compiler needed for Python?

For the most part, Python is an interpreted language and not a compiled one, although compilation is a step. Python code, written in . py file is first compiled to what is called bytecode (discussed in detail further) which is stored with a . pyc or .

Does Python have a use strict?

In summary then: Python does not have a use strict or any near-equivalent as any of the safety features it provides are either mandatory or not available in the Python language, and does not have a use warnings .

What is the use of Python compiler?

A computer program that translates code written in one programming language into another is called a compiler. Python leads the faction of the fastest growing programming languages. As such, there is no scarcity to Python compilers that can cater to varying project needs.


2 Answers

Well, I'm not much of a python programmer, but I'd say that the answer is 'YES'.

Any dynamic language that lets you create a variable with any name at any time, could use a 'strict' pragma.

Strict vars (one of the options for strict in Perl, 'use strict' turns them all on at once) in Perl requires that all variables are declared before they are used. Which means that this code:

my $strict_is_good = 'foo'; $strict_iS_good .= 'COMPILE TIME FATAL ERROR'; 

Generates a fatal error at compile time.

I don't know of a way to get Python to reject this code at compile time:

strict_is_good = 'foo'; strict_iS_good += 'RUN TIME FATAL ERROR'; 

You will get a run-time exception that strict_iS_good is undefined. But only when the code is executed. If your test suite does not have 100% coverage, you can easily ship this bug.

Any time I work in a language that does not have this behavior (PHP for example), I get nervous. I am not a perfect typist. A simple, but hard to spot, typo can cause your code to fail in ways that may be hard to track down.

So, to reiterate, YES Python could use a 'strict' pragma to turn on compile time checks for things that can be checked at compile time. I can't think of any other checks to add, but a better Python programmer probably could think of some.

Note I focus on the pragmatic effect of stict vars in Perl, and am glossing over some of the details. If you really want to know all the details see the perldoc for strict.

Update: Responses to some comments

Jason Baker : Static checkers like pylint are useful. But they represent an extra step that can be and often is skipped. Building some basic checks into the compiler guarantees that these checks are performed consistently. If these checks are controllable by a pragma, even the objection relating to the cost of the checks becomes moot.

popcnt : I know that python will generate a run time exception. I said as much. I advocate compile time checking where possible. Please reread the post.

mpeters : No computer analysis of code can find all errors--this amounts to solving the halting problem. Worse, to find typos in assignments, your compiler would need to know your intentions and find places where your intentions differ from your code. This is pretty clearly impossible.

However this does not mean that no checking should be done. If there are classes of problems that are easy to detect, then it makes sense to trap them.

I'm not familiar enough with pylint and pychecker to say what classes of errors they will catch. As I said I am very inexperienced with python.

These static analysis programs are useful. However, I believe that unless they duplicate the capabilities of the compiler, the compiler will always be in a position to "know" more about the program than any static checker could. It seems wasteful not to take advantage of this to reduce errors where possible.

Update 2:

cdleary - In theory, I agree with you, a static analyzer can do any validation that the compiler can. And in the case of Python, it should be enough.

However, if your compiler is complex enough (especially if you have lots of pragmas that change how compilation occurs, or if like Perl, you can run code at compile time), then the static analyzer must approach the complexity of the compiler/interpreter to do the analysis.

Heh, all this talk of complex compilers and running code at compile time shows my Perl background.

My understanding is that Python does not have pragmas and can not run arbitrary code at compile time. So, unless I am wrong or these features are added, a relatively simple parser in the static analyzer should suffice. It certainly would be helpful to force these checks at every execution. Of course, the way I'd do this is with a pragma.

Once you add pragmas to the mix, you have started down a slippery slope and the complexity of you analyzer must grow in proportion to the power and flexibility you provide in your pragmas. If you are not careful, you can wind up like Perl, and then "only python can parse Python," a future I wouldn't want to see.

Maybe a command line switch would be a better way to add forced static analysis ;)

(In no way do intend to impugn Python's capabilities when I say that it can't futz with compile time behavior like Perl can. I have a hunch that this is a carefully considered design decision, and I can see the wisdom in it. Perl's extreme flexibility at compile time is, IMHO, a great strength and a terrible weakness of the language; I see the wisdom in this approach as well.)

like image 161
daotoad Avatar answered Sep 29 '22 13:09

daotoad


Python does have something that can change script syntax:

from __future__ import print_function 

and various other future-features that have syntax implications. It's just that Python's syntax has been stricter, stabler and more well-defined than historical Perl; the kind of things that ‘strict refs’ and ‘strict subs’ prohibit have never existed in Python.

‘strict vars’ is primarily intended to stop typoed references and missed-out ‘my’s from creating accidental globals (well, package variables in Perl terms). This can't happen in Python as bare assignments default to local declaration, and bare unassigned symbols result in an exception.

(There is still the case where users accidentally try to write-through to a global without declaring it with a ‘global’ statement, causing either an accidental local or, more often, an UnboundLocalError. This tends to be learned fairly quickly, but it is an arguable case where having to declare your locals could help. Although few experienced Python programmers would accept the readability burden.)

Other language and library changes that do not involve syntax are handled through the warnings system.

like image 27
bobince Avatar answered Sep 29 '22 12:09

bobince