gpt4 book ai didi

python - Python 可以识别交互运行的文件的更改吗?

转载 作者:行者123 更新时间:2023-12-01 01:23:37 26 4
gpt4 key购买 nike

我正在做一些故障排除,我很好奇是否可以交互式地运行 Python 脚本,更改脚本中定义的函数,保存文件,然后让交互式 shell 识别更改。以下是我目前正在做的事情的示例:

my_script.py:

def dummy_func():
print('Something')
def main():
dummy_func()
if __name__ == '__main__':
main()

我进入终端并运行:

>python -i my_script.py
Something
>>>

如果我在编辑器中返回 my_script.py 并进行以下更改:

def dummy_func():
print('Something else')

然后返回终端(仍处于打开状态)并重新运行更新后的函数:

>>>dummy_func()
Something
>>>

是否可以做一些事情来代替获得以下行为?:

>>>dummy_func()
Something else
>>>

我知道可以使用 importlibreload 重新加载模块,但据我所知,这不适用于此处,因为我没有导入任何内容。

我认为这可能与 How do I unload (reload) a Python module? 不同。我问是否有办法重新加载您正在通过 python shell 交互运行的当前文件,而该问题是询问如何重新加载已导入到另一个 python 脚本中的模块。

最佳答案

据我所知,简短的答案是:
不,通常,一旦文件被解析、分析并输入到解释器中,Python 解释器就无法识别该文件的更改。

显然,您应该做的是将 .py 文件用作模块,将其作为模块导入到另一个 .py 文件中,然后运行该新文件。这允许您的第一个文件通过交互式解释器重新加载。这是 example :

from importlib import reload  # Python 3.4+ only.
import foo

while True:
# Do some things.
if is_changed(foo):
foo = reload(foo)

我对细节仍然有点模糊,但也许有人可以帮助填写这些内容。据我从下面链接的来源可以看出,解释器基本上采取一些步骤从保存的 python 文件加载程序进入内存(掩盖很多细节)。执行此过程后,解释器不会再次执行它,除非您明确要求它这样做,例如使用 importlib 的 reload() 函数再次执行该过程。

来源:

How do I unload (reload) a Python module? (以上引述)

A Python Interpreter Written in Python :
此链接提供了有关解释器如何工作的更多信息,我发现本节特别有用:

Real Python Bytecode
At this point, we'll abandon our toy instruction sets and switch to real Python bytecode. The structure of bytecode is similar to our toy interpreter's verbose instruction sets, except that it uses one byte instead of a long name to identify each instruction. To understand this structure, we'll walk through the bytecode of a short function. Consider the example below:

>>> def cond():  
... x = 3
... if x < 5:
... return 'yes'
... else:
... return 'no'
...

Python exposes a boatload of its internals at run time, and we can access them right from the REPL. For the function object cond, cond.code is the code object associated it, and cond.code.co_code is the bytecode. There's almost never a good reason to use these attributes directly when you're writing Python code, but they do allow us to get up to all sorts of mischief—and to look at the internals in order to understand them.

>>> cond.__code__.co_code  # the bytecode as raw bytes  
b'd\x01\x00}\x00\x00|\x00\x00d\x02\x00k\x00\x00r\x16\x00d\x03\x00Sd\x04\x00Sd\x00\x00S'
>>> list(cond.__code__.co_code) # the bytecode as numbers
[100, 1, 0, 125, 0, 0, 124, 0, 0, 100, 2, 0, 107, 0, 0, 114, 22, 0, 100, 3, 0, 83,
100, 4, 0, 83, 100, 0, 0, 83]

When we just print the bytecode, it looks unintelligible—all we can tell is that it's a series of bytes. Luckily, there's a powerful tool we can use to understand it: the dis module in the Python standard library.

dis is a bytecode disassembler. A disassembler takes low-level code that is written for machines, like assembly code or bytecode, and prints it in a human-readable way. When we run dis.dis, it outputs an explanation of the bytecode it has passed.

>>> dis.dis(cond)   
2 0 LOAD_CONST 1 (3)
3 STORE_FAST 0 (x)
3 6 LOAD_FAST 0 (x)
9 LOAD_CONST 2 (5)
12 COMPARE_OP 0 (<)
15 POP_JUMP_IF_FALSE 22

4 18 LOAD_CONST 3 ('yes')
21 RETURN_VALUE

6 >> 22 LOAD_CONST 4 ('no')
25 RETURN_VALUE
26 LOAD_CONST 0 (None)
29 RETURN_VALUE

What does all this mean? Let's look at the first instruction LOAD_CONST as an example. The number in the first column (2) shows the line number in our Python source code. The second column is an index into the bytecode, telling us that the LOAD_CONST instruction appears at position zero. The third column is the instruction itself, mapped to its human-readable name. The fourth column, when present, is the argument to that instruction. The fifth column, when present, is a hint about what the argument means.

How does the Python Runtime actually work? :

With Python, it uses an interpreter rather than a compiler. An interpreter works in exactly the same way as a compiler, with one difference: instead of code generation, it loads the output in-memory and executes it directly on your system. (The exact details of how this happens can vary wildly between different languages and different interpreters.)

importlib — The implementation of import :

When reload() is executed:

Python module’s code is recompiled and the module-level code re-executed, defining a new set of objects which are bound to names in the module’s dictionary by reusing the loader which originally loaded the module. The init function of extension modules is not called a second time.

再次,如果我需要编辑此答案以遵循礼仪,请告诉我。

关于python - Python 可以识别交互运行的文件的更改吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53548323/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com