我希望能够从导入的模块中动态检索当前执行的模块或类名.这是一些代码:
foo.py:
def f():
print __name__
Run Code Online (Sandbox Code Playgroud)
bar.py:
from foo import f
def b(): f()
Run Code Online (Sandbox Code Playgroud)
这显然不起作用__name__,因为包含该功能的模块的名称.我希望在foo模块内部访问的是当前正在使用的执行模块的名称foo.因此,在上面的情况下,它将是bar但如果导入任何其他模块foo我想foo动态地访问该模块的名称.
编辑:该inspect模块看起来非常有前途,但它并不完全是我想要的.我希望的是我可以访问的某种全局或环境级变量,它包含当前执行模块的名称.并不是说我不愿意遍历堆栈来查找信息 - 我只是认为Python可能已经暴露了这些数据.
编辑:这是我试图使用它的方式.我有两个不同的Django应用程序,它们都需要将错误记录到文件中.让我们说它们被称为"AppOne"和"AppTwo".我还有一个地方可以记录这些文件:" /home/hare/app_logs".在任何给定点的每个应用程序中,我希望能够导入我的记录器模块并调用将日志字符串写入文件的日志功能.但是,我想要做的是创建一个目录,app_logs该目录是当前应用程序的名称("AppOne"或"AppTwo"),以便每个应用程序的日志文件将进入各自的日志记录目录.
为了做到这一点,我认为最好的办法是对记录器模块能够获得某种形式的全局变量,它表示当前应用程序的名称,因为它是负责了解父日志目录的位置,并创建应用程序的日志目录,如果它还不存在.
S.L*_*ott 49
从评论 - 不是问题.
我很想知道我想做的事情是否可行.
"有可能"的答案总是"是".总是.除非您的问题涉及时间旅行,反重力或永久运动.
由于答案总是"是",你的问题是不正确的.真正的问题是"让我的日志记录模块知道客户端名称的好方法是什么?" 或类似的东西.
答案是"接受它作为参数".不要乱用于检查或寻找神秘的全局或其他技巧.
只需遵循logging.getLogger()的设计模式,并使用显式命名的记录器.一个常见的习语如下
logger= logging.getLogger( __name__ )
Run Code Online (Sandbox Code Playgroud)
它几乎可以完美地处理所有日志命名.
new*_*ver 34
这应该适用于引用当前模块:
import sys
sys.modules[__name__]
Run Code Online (Sandbox Code Playgroud)
Bri*_*ian 19
"当前正在执行的模块"显然是foo,因为它包含当前正在运行的功能 - 我认为更好的描述你想要的是foo的直接调用者的模块(如果你调用af(这可能本身就是foo)从一个函数调用foo函数调用吧.你想要达到多远取决于你想要的东西.
在任何情况下,假设您想要直接调用者,您可以通过向上调用堆栈来获得此调用.这可以通过调用sys._getframe适当数量的级别来完成.
def f():
caller = sys._getframe(1) # Obtain calling frame
print "Called from module", caller.f_globals['__name__']
Run Code Online (Sandbox Code Playgroud)
[编辑]:实际上,如上所述使用检查模块可能是获得堆栈帧的更简洁方法.等效代码是:
def f():
caller = inspect.currentframe().f_back
print "Called from module", caller.f_globals['__name__']
Run Code Online (Sandbox Code Playgroud)
(sys._getframe记录为供内部使用 - inspect模块是更可靠的API)
Sjs*_*van 11
在另一个模块中获取对“__main__”模块的引用:
import sys
sys.modules['__main__']
Run Code Online (Sandbox Code Playgroud)
然后获取模块的文件路径,其中包括其名称:
sys.modules['__main__'].__file__
Run Code Online (Sandbox Code Playgroud)
如果在“__main__”模块中,只需使用: __file__
要仅从文件路径中获取文件名:
import os
os.path.basename(file_path)
Run Code Online (Sandbox Code Playgroud)
要将文件名与其扩展名分开:
file_name.split(".")[0]
Run Code Online (Sandbox Code Playgroud)
要获取类实例的名称:
instance.__class__.__name__
Run Code Online (Sandbox Code Playgroud)
获取类名:
class.__name__
Run Code Online (Sandbox Code Playgroud)
单独使用__file__可为您提供主模块的相对路径和导入模块的绝对路径。意识到这一点,我们可以通过我们的os.path工具的一些帮助不断地获取模块文件。
仅对于文件名使用__file__.split(os.path.sep)[-1].
供完整路径使用os.path.abspath(__file__)。
演示:
/tmp $ cat f.py
from pprint import pprint
import os
import sys
pprint({
'sys.modules[__name__]': sys.modules[__name__],
'__file__': __file__,
'__file__.split(os.path.sep)[-1]': __file__.split(os.path.sep)[-1],
'os.path.abspath(__file__)': os.path.abspath(__file__),
})
/tmp $ cat i.py
import f
Run Code Online (Sandbox Code Playgroud)
结果:
## 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'}
Run Code Online (Sandbox Code Playgroud)
如果你想去掉末尾的“.py”,你可以轻松做到。(但不要忘记您可以运行“.pyc”。)
如果您只需要文件名:
file_name = __file__.split("/")[len(__file__.split("/"))-1]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
74554 次 |
| 最近记录: |