Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

self modifying python script

I want to create python script which can modify code in that script itself using Python Language Services or using any other way.
e.g. A script which keep track of its count of successfull execution

import re
COUNT = 0

def updateCount():
    # code to update second line e.g. COUNT = 0
    pass

if __name__ == '__main__':
    print('This script has run {} times'.format(COUNT))
    updateCount()

On successful execution of this script code should get changed to

import re
COUNT = 1

def updateCount():
    # code to update second line e.g. COUNT = 0
    pass

if __name__ == '__main__':
    print('This script has run {} times'.format(COUNT))
    updateCount()

Simple approach came to my mind was to open __file__ in write mode and do requried modification using reguler expessions etc. But that did not work I got exception io.UnsupportedOperation: not readable. Even if this approach would be working then it would be very risky because it can spoil my whole script. so I am looking for solution using Python Language Services.

like image 701
Alok Avatar asked Jul 18 '17 19:07

Alok


2 Answers

Yes, you can use the language services to achieve self-modification, as in following example:

>>> def foo(): print("original foo")
>>> foo()
original foo
>>> rewrite_txt="def foo(): print('I am new foo')"
>>> newcode=compile(rewrite_text,"",'exec')
>>> eval(newcode)
>>> foo()
I am new foo

So, by new dynamically generated code you can replace stuff contained in the original source file, without modifying the file itself.

like image 66
ddbug Avatar answered Nov 05 '22 22:11

ddbug


A python script is nothing more than a text file. So, you are able to open it as an external file and read & write on that. (Using __file__ variable you can get the exact name of your script):

def updateCount():
    fin = open(__file__, 'r')
    code = fin.read()
    fin.close()

    second_line = code.split('\n')[1]
    second_line_parts = second_line.split(' ')
    second_line_parts[2] = str(int(second_line_parts[2])+1)

    second_line = ' '.join(second_line_parts)
    lines = code.split('\n')
    lines[1] = second_line
    code = '\n'.join(lines)

    fout = open(__file__, 'w')
    fout.write(code)
    fout.close()
like image 25
kyriakosSt Avatar answered Nov 05 '22 20:11

kyriakosSt