簡體   English   中英

Python是否可以識別對以交互方式運行的文件的更改?

[英]Can Python recognize changes to a file that it is running interactively?

我當時在做一些麻煩的事,我很好奇是否可以交互運行python腳本,更改腳本中定義的功能,保存文件,然后讓交互式外殼程序識別更改。 這是我目前正在做的一個例子:

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

我知道可以使用importlib重新加載模塊,然后重新加載,但據我所知這不適用於此處,因為我沒有導入任何內容。 我對stackoverflow還是比較陌生,所以請告訴我是否需要提供更多詳細信息或以其他方式詢問。 謝謝。

編輯; 我認為這可能與我如何卸載(重新加載)Python模塊不同?
我問是否有一種方法可以通過python shell重新加載正在交互運行的當前文件,而該問題詢問如何重新加載已導入到另一個python腳本中的模塊。 我編輯了答案,以包括對該問題的引用。

根據我的發現,簡短的答案是:
不,通常,一旦文件被解析,分析並輸入到解釋器中,Python解釋器就無法識別該文件的更改。

您應該做的顯然是將.py文件用作模塊,將其作為模塊導入另一個.py文件,然后運行該新文件。 這使您的第一個文件可以通過交互式解釋器重新加載。 這是一個例子

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()函數再次執行該過程。

資料來源:

如何卸載(重新加載)Python模塊? (以上引用)

用Python編寫的Python解釋器
該鏈接提供了有關解釋器如何工作的更多信息,我發現本節特別有用:

真正的Python字節碼
在這一點上,我們將放棄玩具指令集,而切換到真正的Python字節碼。 字節碼的結構類似於我們的玩具解釋器的詳細指令集,不同之處在於它使用一個字節代替長名稱來標識每條指令。 為了理解這種結構,我們將遍歷一個簡短函數的字節碼。 考慮下面的示例:

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

Python在運行時公開了其內部組件,我們可以從REPL中直接訪問它們。 對於功能對象cond,cond。 code是與之關聯的代碼對象,然后繼續。 code .co_code是字節碼。 在編寫Python代碼時,幾乎從來沒有直接使用這些屬性的充分理由,但是它們的確使我們能夠直面各種惡作劇,並查看內部結構以理解它們。

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

當我們僅打印字節碼時,它看起來就難以理解,我們只能說它是一系列字節。 幸運的是,我們可以使用一個強大的工具來理解它:Python標准庫中的dis模塊。

dis是字節碼反匯編程序。 反匯編程序采用為機器編寫的低級代碼(例如匯編代碼或字節碼),並以人類可讀的方式打印它們。 當我們運行dis.dis時,它將輸出已通過的字節碼的說明。

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

這是什么意思呢? 讓我們以第一條指令LOAD_CONST為例。 第一列(2)中的數字顯示了Python源代碼中的行號。 第二列是字節碼的索引,告訴我們LOAD_CONST指令出現在零位置。 第三列是指令本身,映射到其可讀名稱。 第四列(如果存在)是該指令的參數。 出現在第五列時,它暗示了該參數的含義。

Python運行時實際上是如何工作的?

在Python中,它使用解釋器而不是編譯器。 解釋器的工作方式與編譯器完全相同,但有一個區別:解釋器代替代碼生成,而是將輸出加載到內存中並直接在系統上執行。 (如何發生這種情況的確切細節在不同的語言和不同的解釋器之間可能會有很大差異。)

importlib —導入的實現

當執行reload()時:

重新編譯Python模塊的代碼並重新執行模塊級代碼,從而通過重新使用最初加載模塊的加載器來定義一組新對象,這些對象綁定到模塊字典中的名稱。 擴展模塊的init函數不會被第二次調用。

同樣,請讓我知道是否需要編輯此答案以遵循禮節。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM