如何动态获取当前执行的Python脚本名?

文章目录

1、情景描述

当我们在使用Python进行一些操作时,如果我们希望我们封装的模块里的方法能够在给使用者调用的同时可以获取到调用者当前正在执行的Python脚本名,以做一些后续操作。这听起来好像跟反射有异曲同工之处。反射可以实现吗?

来看一个需求:

现有一个用于封装工具API的模块:module.py,如下:

python 复制代码
def do():
    ...
    # 处理中间过程
    ...
    return 'result'

该模块中有一个方法do()供调用者调用。现在有一个需求:该方法中的处理中间过程需要获取到调用者当前执行的Python脚本名,并做一些处理操作,最后返回给调用者结果

这种情况需要如何实现呢?可以尝试以下办法:

2、如何获取调用者脚本名?

2.1、方式1:使用反射?

在Java中,我们知道反射是指在类加载时动态获取类的成员(包括类、属性、方法等),以对类和对象进行修改。在Python中,这类似。反射可以动态获取对象的属性和方法,但对于Python脚本,好像和它没啥关系吧?更何况Python脚本名呢

2.2、方式2:使用os模块?

Python内置的os模块提供一些文件和路径处理的方法,兴许这里面有可以帮我们完成这个需求的方法呢

os模块中的__file__属性可用于返回当前脚本的文件路径,包括文件名,结合os.path.basename()是否可以获取调用者的脚本名呢?马上进行下面尝试:

工具API模块:module.py

python 复制代码
import os

def do():
    print(os.path.basename(__file__))

调用者模块:client.py

python 复制代码
from module import do

do()

'''
module.py
'''

什么情况?我要获取的是调用者脚本名,我需要你打印出来的是client.py,而不是module.py

从结果可见,这种方式不太行啊

2.3、使用sys模块?

Python内置的sys模块主要用于Python解释器和系统之间的交互,例如获取系统环境变量。sys可以实现吗?

sys提供了一个函数sys._getframe()用于查看函数被什么函数调用及被第几行调用以及被调用函数所在的文件

sys._getframe(depth)从调用堆栈返回一个框架对象。 如果给定了可选整数depth,则返回在堆栈顶部以下调用多次的框架对象。depth的默认值为0,返回调用堆栈顶部的帧。如果参数比调用堆栈更深,则会引发ValueError异常

sys._getframe()的更多使用见文末总结

来试一下吧

工具API模块:module.py

python 复制代码
import os
import sys

def do():
    print(os.path.basename(sys._getframe().f_back.f_code.co_filename))

调用者模块:client.py

python 复制代码
from module import do

do()

'''
client.py
'''

嗯嗯,sys模块的sys._getframe()可以帮我们完成上述需求,但较为复杂,不好理解

2.4、sys获取argv

sys提供的sys.argv[]可用于访问命令行参数。然而,sys.argv[0]可用于获取正在执行的Python脚本本身

这可能是最好的一种方式。示例如下:

工具API模块:module.py

python 复制代码
import os
import sys

def do():
    print(os.path.basename(sys.argv[0]))

调用者模块:client.py

python 复制代码
from module import do

do()

'''
client.py
'''

这不是更完美吗?

3、sys._getframe()总结

sys._getframe()的常用使用总结如下:

python 复制代码
'''
sys._getframe(0)                       # 被调用模块层
sys._getframe(1)                       # 调用者模块层
sys._getframe().f_back                 # 调用者模块层,和sys._getframe(1)相同
sys._getframe(0).f_code.co_filename    # 被调用模块当前文件名,也可以通过__file__获得
sys._getframe(1).f_code.co_filename    # 调用者模块当前文件名,和sys._getframe().f_back.f_code.co_filename相同
sys._getframe(0).f_code.co_name        # 被调用模块层当前函数名
sys._getframe(1).f_code.co_name        # 调用者模块层调用所在函数名,如果没有,则返回<module>
sys._getframe(0).f_lineno              # 被调用模块层被调用函数的行号
sys._getframe(1).f_lineno              # 调用者模块层调用该函数所在的行号
'''
相关推荐
学测绘的小杨7 小时前
CompassFusion:一个从 GNSS 到 GNSS/INS 组合导航的独立工程包
python
zzzzzz31014 小时前
当产品经理说这个很简单:我用Python自动化处理奇葩需求的实战指南
python·pycharm·产品经理
雪隐14 小时前
个人电脑玩AI-06让5060 Ti给你打工——不光能画画,Qwen3-TTS还能学人说话,连我老板都信了!
人工智能·后端·python
兵慌码乱1 天前
面向桌面端的资产管理系统分层架构设计与核心模块实现
python·系统架构·sqlite·pyqt5·数据库设计·桌面应用开发·mvc架构
hboot1 天前
AI工程师第三课 - 机器学习基础
python·scikit-learn·kaggle
顾林海1 天前
Agent入门阶段-编程基础-Python:流程控制
python·agent·ai编程
呱呱复呱呱1 天前
Django CBV 源码解读:一个请求是怎么找到你的 get() 方法的
python·django
曲幽2 天前
刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API
python·fastapi·web·translate·goldendict·libretranslate·stardict·pystardict
荣码2 天前
用Streamlit给AI应用套个界面,10行代码出Web页面
java·python
兵慌码乱2 天前
基于Python+PyQt5+SQLite的药房管理系统实现:事务一致性与界面解耦全流程解析
python·sqlite·信号与槽·pyqt5·数据库设计·桌面应用开发·事务处理