博客 / 詳情

返回

Python動態執行代碼修改命名空間

在前面《Python 代碼動態執行初探》中講到過如何用exec和eval函數動態執行代碼,也描述瞭如何限制其命名空間,避免動態代碼造成環境“污染”。

不過,有的時候,我們的確想要讓動態代碼生成一些局部或全局的定義——比如一個變量名——讓原始代碼或者後面的動態代碼可以繼續使用。像下面這樣直接定義是無法生效的:

def f():
    a = 1
    exec("a = 3")
    print(a)

此時打印的結果會是1,也就是説exec中對a的修改被丟棄了。不過可以採用locals參數來取回修改:

def foo():
    ldict = {}
    exec("a=3",globals(),ldict)
    a = ldict['a']
    print(a)

這裏的打印結果就是3了。

本文的示例代碼取自stack overflow的一篇問答


2021-11-17更新
注意:在pycharm裏,默認的source root就是項目根目錄,這時不要在項目內部,再設置source folder了,要不然就會出現同一個Module,可以從不同級別import的問題。

我就曾經犯了這個錯誤,把一個項目子文件夾設置成source folder:pycharm source folder snapshot
導致自動生成的import,全都少一級目錄,比如像下面這樣:

from core.data.Action import Action
class Executor

而實際上寫全路徑也能成功import:

from simplerpa.core.data.Action import Action
class STATE

這個錯誤還很隱蔽,因為平時使用沒有任何問題,直到有一個類成員屬性承擔了本文上面提到的ldict功能,但裏面保存的變量,在Executor執行的時候都丟失了,才發現原來從不同路徑import的同一個類,不能共享類成員。

user avatar backofhan 頭像 opsdev365 頭像 feibendetiangua 頭像 8848_62c77d4bb2532 頭像 sintrb 頭像
5 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.