2009-03-02 57 views
22

我希望能夠從導入的模塊中動態檢索當前正在執行的模塊或類名。下面是一些代碼:如何在Python中訪問當前正在執行的模塊或類名?

foo.py:

def f(): 
    print __name__ 

bar.py:

from foo import f 

def b(): f() 

這顯然不爲__name__工作是包含模塊的名稱功能。我想在foo模塊內部訪問的是當前使用foo的執行模塊的名稱。所以在上面的情況下,它將是bar,但是如果有任何其他模塊導入foo,我希望foo動態訪問該模塊的名稱。

編輯:inspect模塊看起來很有前途,但它不是我正在尋找。我所希望的是我可以訪問的某種全局或環境級別的變量,它包含當前執行模塊的名稱。並不是說我不願意遍歷堆棧來查找這些信息 - 我只是認爲Python可能已經公開了這些數據。

編輯:這是我如何使用這個。我有兩個不同的Django應用程序,都需要將錯誤記錄到文件。可以說他們被稱爲「AppOne」和「AppTwo」。我也有一個我想要登錄這些文件的地方:「/home/hare/app_logs」。在任何給定點的每個應用程序中,我希望能夠導入我的記錄器模塊並調用將日誌字符串寫入文件的日誌函數。但是我想要做的是創建一個名爲app_logs的目錄,它是當前應用程序的名稱(「AppOne」或「AppTwo」),以便每個應用程序的日誌文件將放入其各自的日誌目錄中。

爲了做到這一點,我認爲最好的方式是記錄器模塊有權訪問某種表示當前應用程序名稱的全局變量,因爲它負責知道父記錄目錄的位置,如果應用程序的日誌目錄尚不存在,則創建它。

+0

你爲什麼要打破這樣的責任分配? – 2009-03-02 16:06:28

+1

我在一個日誌記錄模塊中使用它 - 我想能夠告訴哪個外部模塊正在嘗試記錄,而無需調用者傳遞某種密鑰。 – 2009-03-02 16:10:25

+0

您是否正在尋找啓動程序執行的模塊(即:__name__ =='__main__'的模塊?或者直接稱爲foo.f()的模塊,每次foo.f()都可能不同所謂的「 – 2009-03-02 16:18:39

回答

40

從評論 - 而不是問題。

我只是好奇,看看我正在嘗試做什麼是可能的。

「是否可能」的答案始終爲「是」。總是。除非你的問題涉及時間旅行,反重力或永久運動。

由於答案總是「是」,所以你的問題是不合格的。真正的問題是「什麼是讓我的日誌記錄模塊知道客戶端名稱的好方法?」或類似的東西。

答案是「接受它作爲參數」。不要亂用檢查或尋找神祕的全局或其他技巧。

只需遵循logging.getLogger()的設計模式並使用顯式指定的記錄器即可。一個常見的用法如下

logger= logging.getLogger(__name__) 

這幾乎可以處理所有的日誌命名。

3

我不認爲這是可能的,因爲這是foo的範圍。 foo只會意識到它的內部範圍,因爲它可能被無數其他模塊和應用程序所調用。

11

我想你想用的是inspect模塊,來檢查python運行時棧。看看這個tutorial。我認爲它提供了一個你想要做的幾乎確切的例子。

15

「當前正在執行的模塊」顯然是foo,因爲它包含了當前正在運行的函數 - 我認爲你想要的是foo的直接調用者模塊的更好的描述(如果你是在foo中調用函數foo中的af()函數調用foo中的函數,你想上漲的距離取決於你想要的這個值

在任何情況下,假設你想要直接調用者,你可以獲得這個可以通過調用sys._getframe來完成調用堆棧,可以通過適當數量的級別來執行。

def f(): 
    caller = sys._getframe(1) # Obtain calling frame 
    print "Called from module", caller.f_globals['__name__'] 

[編輯]:實際上,使用如上述的建議inspect模塊可能是獲得所述棧幀的更清潔的方式。等效代碼:

def f(): 
    caller = inspect.currentframe().f_back 
    print "Called from module", caller.f_globals['__name__'] 

(sys._getframe被記錄爲供內部使用 - 在檢查模塊是一個更可靠的API)

1

這已經有一段時間,因爲我做了蟒蛇,但我相信你可以通過其traceback訪問調用者的全局和當地人。

7

__file__是調用當前模塊的路徑。

24

這應該引用當前模塊的工作:

import sys 
sys.modules[__name__] 
1

要獲得一個參考「__main__」模塊時,在另一:

import sys 
sys.modules['__main__'] 

然後,爲了獲得模塊的文件路徑,包括其名稱:

sys.modules['__main__'].__file__ 

如果在「__main__」模塊中,只需使用: __file__

從文件路徑獲取是文件名:

import os 
os.path.basename(file_path) 

從它的擴展分開的文件名:

file_name.split(".")[0] 

爲了獲得一個類的實例的名稱:

instance.__class__.__name__ 

要獲得一個類的名稱:

class.__name__ 
2

單獨使用__file__會爲您提供主模塊的相對路徑和導入模塊的絕對路徑。意識到這一點,我們可以通過我們的os.path工具的一些幫助,不斷獲得模塊文件。

對於文件名只能使用__file__.split(os.path.sep)[-1]

如需完整路徑使用os.path.abspath(__file__)

演示:

​​3210

結果:

## on *Nix ## 

/tmp $ python3 f.py 
{'sys.modules[__name__]': <module '__main__' from 'f.py'>, 
'__file__': 'f.py', 
'__file__.split(os.path.sep)[-1]': 'f.py', 
'os.path.abspath(__file__)': '/tmp/f.py'} 

/tmp $ python3 i.py 
{'sys.modules[__name__]': <module 'f' from '/tmp/f.pyc'>, 
'__file__': '/tmp/f.pyc', 
'__file__.split(os.path.sep)[-1]': 'f.pyc', 
'os.path.abspath(__file__)': '/tmp/f.pyc'} 

## on Windows ## 

PS C:\tmp> python3.exe f.py 
{'sys.modules[__name__]': <module '__main__' from 'f.py'>, 
'__file__': 'f.py', 
'__file__.split(os.path.sep)[-1]': 'f.py', 
'os.path.abspath(__file__)': 'C:\\tools\\cygwin\\tmp\\f.py'} 

PS C:\tmp> python3.exe i.py 
{'sys.modules[__name__]': <module 'f' from 'C:\\tools\\cygwin\\tmp\\f.py'>, 
'__file__': 'C:\\tools\\cygwin\\tmp\\f.py', 
'__file__.split(os.path.sep)[-1]': 'f.py', 
'os.path.abspath(__file__)': 'C:\\tools\\cygwin\\tmp\\f.py'} 

如果要剝離 '的.py' 關結束時,你可以輕鬆辦到。 (但是不要忘了,你可能會遇到一個「.pyc文件」來代替。)

1

如果你想要的文件的唯一名稱:

file_name = __file__.split("/")[len(__file__.split("/"))-1] 
相關問題