自修改python脚本

时间:2017-07-18 19:38:47

标签: python self-modifying

我想创建python脚本,它可以使用Python Language Services或使用任何其他方式修改该脚本中的代码。
例如跟踪其成功执行次数的脚本

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()

成功执行此脚本后,代码应更改为

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()

我想到的简单方法是在写入模式下打开__file__并使用调整程序执行等方式进行必要的修改。但是这不起作用我得到了异常io.UnsupportedOperation: not readable。即使这种方法有效,也会有很大的风险,因为它会破坏我的整个脚本。所以我正在寻找使用Python语言服务的解决方案。

3 个答案:

答案 0 :(得分:5)

python脚本只不过是一个文本文件。因此,您可以将其作为外部文件打开并阅读&写下来。 (使用__file__变量,您可以获得脚本的确切名称):

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()

答案 1 :(得分:3)

是的,您可以使用语言服务来实现自我修改,如下例所示:

>>> 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

因此,通过新的动态生成的代码,您可以替换原始源文件中包含的内容,而无需修改文件本身。

答案 2 :(得分:1)

@kyriakosSt的答案有效,但是硬编码cv::setNumThreads(4);的赋值必须在第二行,随着时间的流逝,由于源被修改为其他原因而导致行数发生变化,这很容易导致意外行为

对于更健壮的解决方案,您可以使用COUNT的子类来使用固定器来重构lib2to3,以使用lib2to3.refactor.RefactoringTool来解析和更新源代码。带有一个模式,该模式查找带有模式lib2to3.fixer_base.BaseFix的表达式语句,以及一个'COUNT' '=' any方法,该方法通过增加其整数值来更新最后一个子节点:

transform

演示:https://repl.it/@blhsing/MushyStrangeClosedsource