如果我在Python脚本'运行时修改它会发生什么?

想象一下,运行一个python脚本需要很长时间,如果我在运行时修改它会发生什么?结果会不同吗?

76175 次浏览

没有,因为Python将脚本预编译为PYC文件并启动该文件。

然而,如果发生了某种异常,你可能会得到一个略微误导的解释,因为行X可能与你启动脚本之前有不同的代码。

什么都没有发生。一旦脚本加载到内存中并运行,它将保持如下所示。

一个“auto-reloading"特性可以在你的代码中实现,就像Flask和其他框架一样。

不同。如果一个python脚本链接到其他修改过的文件,那么当然会加载更新的版本。但是如果源不指向任何其他文件,它就会运行缓存中的所有脚本,只要它运行。下次就能看到变化了…

如果关于自动应用更改,是的,@pcbacterio是正确的。它可以做thar,但脚本,它只记得最后的动作/事情是做什么,并检查当文件被修改重新运行它(所以它几乎不可见)

=]

当你运行一个python程序并启动解释器时,发生的第一件事是:

  • 模块sysbuiltins被初始化
  • __main__模块被初始化,这是你作为参数提供给解释器的文件;这将导致代码执行

当模块初始化时,运行它的代码,在过程中定义类、变量和函数。你的模块(即主文件)的第一步可能是导入其他模块,这将再次以相同的方式初始化;然后,它们产生的名称空间可以供您的模块使用。导入过程的结果部分是内存中的模块(python-)对象。该对象确实有指向.py和.pyc的字段内容,但这些内容不再计算:模块对象被缓存和它们的源文件从未运行两次。因此,在执行时使用之后在磁盘上修改模块没有效果。它可以在出于内省目的读取源代码时产生影响,例如抛出异常时,或者通过模块检查

这就是为什么在添加不打算在导入模块时运行的代码时,检查if __name__ == "__main__"是必要的。以main方式运行该文件等同于导入该文件,除了__name__具有不同的值。


来源:

这是一个有趣的问题。答案是“视情况而定”。

考虑下面的代码:

"Example script showing bad things you can do with python."


import os


print('this is a good script')
with open(__file__, 'w') as fdesc:
fdesc.write('print("this is a bad script")')


import bad

试着将以上文件保存为"/tmp/bad.py"然后执行“cd /tmp"最后是"python3 bad. pyquot;看看会发生什么。

在我的ubuntu 20系统上,我看到输出:

this is a good script
this is a bad script

所以,你问题的答案是“视情况而定”。如果你不做任何奇怪的事情,那么脚本就在内存中,你就没事了。但是python是一种非常动态的语言,所以有多种方法来修改你的“脚本”。让它影响输出。

如果您不打算做任何奇怪的事情,那么可能需要注意的事情之一是函数中的导入。

下面是另一个例子,它说明了这个想法(保存为"/tmp/modify.py"cd /tmp"然后“python3 modify. pyquot;运行)。下面定义的fiddle函数模拟你在脚本运行时修改脚本(如果需要,你可以删除fiddle函数,在倒数第二行放入time.sleep(300),然后自己修改文件)。

问题是,由于show函数是在函数内部而不是在模块顶部进行导入,因此直到函数被调用才会发生导入。如果在调用show之前修改了脚本,则将使用修改后的脚本版本。

如果您在修改运行脚本时发现了令人惊讶或意想不到的行为,我建议您在函数中寻找import语句。有时这样做是有很好的理由的,所以你会不时地在人们的代码和一些库中看到它。

下面演示了函数内部的导入如何导致奇怪的效果。你可以尝试这是vs注释掉fiddle函数的调用,以查看在脚本运行时修改脚本的效果。

"Example showing import in a function"


import time


def yell(msg):
"Yell a msg"
return f'#{msg}#'
    

def show(msg):
"Print a message nicely"
import modify
print(modify.yell(msg))


def fiddle():
orig = open(__file__).read()
with open(__file__, 'w') as fdesc:
modified = orig.replace('{' + 'msg' + '}', '{msg.upper()}')
fdesc.write(modified)


fiddle()
show('What do you think?')

不,结果将不反映保存后的更改。当运行常规的python文件时,结果不会改变。您必须保存更改并重新运行程序。

执行以下脚本:

from time import sleep


print("Printing hello world in: ")
for i in range(10, 0, -1):
print(f"{i}...")
sleep(1)
    

print("Hello World!")

然后将“Hello World!”到“你好,StackOverflow!”当它在倒计时时,它仍然会输出“Hello world”。

这与你在问题中描述的略有不同,但它是有效的:

my_string = "Hello World!"


line = input(">>> ")
exec(line)


print(my_string)

测试运行:

>>> print("Hey")
Hey
Hello World!


>>> my_string = "Goodbye, World"
Goodbye, World

看,你可以改变你的“负载”行为。动态代码。