没有什么变化,因为Python会将您的脚本预编译成PYC文件并启动它。
但是,如果发生某种异常,您可能会得到一个稍微误导的解释,因为在您启动脚本之前,行X的代码可能已经发生了变化。
sys
和builtins
被初始化。
- 初始化__main__
模块,这是你作为参数给解释器的文件;这将导致你的代码被执行。if __name__ == "__main__"
。将文件作为主文件运行等效于导入该文件,除了__name__
具有不同的值。
来源:
__main__
模块是什么:__main__
- 顶层代码环境这是一个有趣的问题。答案是“取决于情况”。
考虑以下代码:
"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.py”并查看结果。
在我的Ubuntu 20系统上,我看到输出:
this is a good script
this is a bad script
所以,你问题的答案是“这取决于情况”。如果你没有做任何奇怪的事情,那么脚本就在内存中,一切都好。但是Python是一种非常动态的语言,因此有许多方法可以修改你的“脚本”并影响输出结果。
如果你不想做任何奇怪的事情,那么需要注意的一点是函数内部的导入。
以下是另一个示例,说明了这个想法(将其保存为“/tmp/modify.py”,然后执行“cd /tmp”和“python3 modify.py”)。下面定义的“fiddle”函数模拟了在脚本运行时修改脚本的操作(如果需要,你可以删除“fiddle”函数,在倒数第二行放置“time.sleep(300)”,然后自己修改文件)。
重点是,由于“show”函数在函数内部而不是在模块顶部进行导入,因此导入操作只有在调用该函数时才会发生。如果在调用“show”函数之前修改了脚本,则会使用你修改后的版本。
如果你对修改正在运行的脚本产生意外或意想不到的行为,请尝试查找函数内部的导入语句。有时候这样做是有好的原因的,所以你也会在一些人的代码以及某些库中看到它。
下面是说明导入语句在函数内部会产生奇怪效果的演示。你可以尝试直接运行或注释掉对“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?')
就像这个答案所说的一样,没有什么问题。此外,当涉及到multiprocessing
时,我做了实验。请将以下脚本保存为x.py
:
import multiprocessing
import time
def f(x):
print(x)
time.sleep(10)
if __name__ == '__main__':
with multiprocessing.Pool(2) as pool:
for _ in pool.imap(f, ['hello'] * 5):
pass
在执行了python3 x.py
命令后,前两个“hello”被打印出来后,我将['hello']
修改为['world']
并观察发生了什么。没有发生有趣的事情。结果仍然是:
hello
hello
hello
hello
hello
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!”更改为“Hello StackOverflow!”,它仍然会输出“Hello World”。
什么也不会发生。一旦脚本被加载到内存中并运行,它将保持这样。
“自动重新加载”功能可以在您的代码中实现,就像Flask和其他框架一样。
这与您在问题中描述的略有不同,但它可以工作:
my_string = "Hello World!"
line = input(">>> ")
exec(line)
print(my_string)
测试运行:
>>> print("Hey")
Hey
Hello World!
>>> my_string = "Goodbye, World"
Goodbye, World
你可以动态地改变你的“已加载”代码的行为。
如果一个Python脚本链接到其他修改过的文件,那么它将加载更新的版本。但是,如果源代码没有指向任何其他文件,只要运行了脚本,它就会从缓存中运行所有脚本。更改将在下一次可见...
如果关于在进行更改时自动应用更改-是的,@pcbacterio是正确的。可以做到这一点,但是执行此操作的脚本只会记住上次操作/正在进行的事情,并在文件被修改时检查以重新运行它(因此几乎不可见)
=]