Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignore the rest of the python file

My python scripts often contain "executable code" (functions, classes, &c) in the first part of the file and "test code" (interactive experiments) at the end.

I want python, py_compile, pylint &c to completely ignore the experimental stuff at the end.

I am looking for something like #if 0 for cpp.

How can this be done?

Here are some ideas and the reasons they are bad:

  1. sys.exit(0): works for python but not py_compile and pylint
  2. put all experimental code under def test():: I can no longer copy/paste the code into a python REPL because it has non-trivial indent
  3. put all experimental code between lines with """: emacs no longer indents and fontifies the code properly
  4. comment and uncomment the code all the time: I am too lazy (yes, this is a single key press, but I have to remember to do that!)
  5. put the test code into a separate file: I want to keep the related stuff together

PS. My IDE is Emacs and my python interpreter is pyspark.

like image 561
sds Avatar asked Aug 12 '15 15:08

sds


5 Answers

Use ipython rather than python for your REPL It has better code completion and introspection and when you paste indented code it can automatically "de-indent" the pasted code.

Thus you can put your experimental code in a test function and then paste in parts without worrying and having to de-indent your code.

If you are pasting large blocks that can be considered individual blocks then you will need to use the %paste or %cpaste magics.

eg.

    for i in range(3):
        i *= 2 
        # with the following the blank line this is a complete block

        print(i)

With a normal paste:

In [1]:         for i in range(3):
   ...:                 i *= 2
   ...:     

In [2]:             print(i)
4

Using %paste

In [3]: %paste
        for i in range(10):
            i *= 2

            print(i)

## -- End pasted text --
0
2
4

In [4]: 

PySpark and IPython

It is also possible to launch PySpark in IPython, the enhanced Python interpreter. PySpark works with IPython 1.0.0 and later. To use IPython, set the IPYTHON variable to 1 when running bin/pyspark:1

$ IPYTHON=1 ./bin/pyspark
like image 119
Dunes Avatar answered Oct 18 '22 10:10

Dunes


Unfortunately, there is no widely (or any) standard describing what you are talking about, so getting a bunch of python specific things to work like this will be difficult.

However, you could wrap these commands in such a way that they only read until a signifier. For example (assuming you are on a unix system):

cat $file | sed '/exit(0)/q' |sed '/exit(0)/d' 

The command will read until 'exit(0)' is found. You could pipe this into your checkers, or create a temp file that your checkers read. You could create wrapper executable files on your path that may work with your editors.

Windows may be able to use a similar technique.

I might advise a different approach. Separate files might be best. You might explore iPython notebooks as a possible solution, but I'm not sure exactly what your use case is.

like image 45
Aaron Schif Avatar answered Oct 18 '22 09:10

Aaron Schif


Follow something like option 2.
I usually put experimental code in a main method.

def main ():
    *experimental code goes here *

Then if you want to execute the experimental code just call the main.

main()
like image 24
Spilker22 Avatar answered Oct 18 '22 10:10

Spilker22


With python-mode.el mark arbitrary chunks as section - for example via py-sectionize-region.

Than call py-execute-section.

Updated after comment:

python-mode.el is delivered by melpa.

M-x list-packages RET

Look for python-mode - the built-in python.el provides 'python, while python-mode.el provides 'python-mode.

Developement just moved hereto: https://gitlab.com/python-mode-devs/python-mode

like image 1
Andreas Röhler Avatar answered Oct 18 '22 11:10

Andreas Röhler


I think the standard ('Pythonic') way to deal with this is to do it like so:

class MyClass(object):
    ...

def my_function():
    ...

if __name__ == '__main__':
    # testing code here

Edit after your comment

I don't think what you want is possible using a plain Python interpreter. You could have a look at the IEP Python editor (website, bitbucket): it supports something like Matlab's cell mode, where a cell can be defined with a double comment character (##):

## main code

class MyClass(object):
    ...

def my_function():
    ...

## testing code

do_some_testing_please()

All code from a ##-beginning line until either the next such line or end-of-file constitutes a single cell. Whenever the cursor is within a particular cell and you strike some hotkey (default Ctrl+Enter), the code within that cell is executed in the currently running interpreter. An additional feature of IEP is that selected code can be executed with F9; a pretty standard feature but the nice thing here is that IEP will smartly deal with whitespace, so just selecting and pasting stuff from inside a method will automatically work.

like image 1
EelkeSpaak Avatar answered Oct 18 '22 11:10

EelkeSpaak