How to dynamically get the name of the currently executing Python script?




1. Scenario description


When we use Python to perform some operations, if we want the method in the module we encapsulate to be called by the user, we can also obtain the name of the Python script currently being executed by the caller to perform some subsequent operations. This sounds similar to reflection. Is reflection possible?

Let’s look at a requirement:

There is currently a module for encapsulating tool API:module.py, as follows:

def do():
    ...
    # 处理中间过程
    ...
    return 'result'

There is a method in this moduledo() for the caller to call. Now there is a requirement: 处理中间过程 in this method needs to get the name of the Python script currently executed by the caller, do some processing operations, and finally return the result to the caller

How does this situation need to be achieved? You can try the following methods:

2. How to get the caller script name?


2.1. Method 1: Use reflection?

In Java, we know that reflection refers to dynamically obtaining the members of a class (including classes, properties, methods, etc.) during class loading to modify classes and objects. In Python, this is similar. Reflection can dynamically obtain the properties and methods of objects, but for Python scripts, it seems to have nothing to do with it, right? Not to mention the Python script name

2.2. Method 2: Use the os module?

Python's built-in os module provides some methods for file and path processing. Maybe there is a method that can help us complete this requirement.

The__file__ attribute in the os module can be used to return the file path of the current script, including the file name. Combined withos.path.basename(), whether the caller's script name can be obtained Woolen cloth? Try the following now:

Tool API model:module.py:

import os

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

Caller module:client.py:

from module import do

do()

'''
module.py
'''

What's going on? What I want to get is the caller script name. What I need you to print is client.py, not module.py

It can be seen from the results that this method is not very effective.

2.3. Use sys module?

Python's built-in sys module is mainly used for interaction between the Python interpreter and the system, such as obtaining system environment variables. Can sys be implemented?

sys provides a functionsys._getframe() used to check what function is called, which line it is called on, and the file where the called function is located

sys._getframe(depth)Return a frame object from the call stack. If the optional integer depth is given, returns the frame object called multiple times below the top of the stack. The default value for depth is 0, which returns the frame at the top of the call stack. If the argument is deeper than the call stack, a ValueError exception is raised

sys._getframe()For more uses, see the summary at the end of the article

Come and try it

Tool API model:module.py:

import os
import sys

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

Caller module:client.py:

from module import do

do()

'''
client.py
'''

Hmm, the sys modulesys._getframe() can help us complete the above requirements, but it is more complicated and difficult to understand

2.4. sys gets argv

sys providessys.argv[] which can be used to access command line parameters. However, sys.argv[0]can be used to obtain the executing Python script itself

This is probably the best way. Examples are as follows:

Tool API model:module.py:

import os
import sys

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

Caller module:client.py:

from module import do

do()

'''
client.py
'''

Isn't this more perfect?

3. sys._getframe() summary


sys._getframe()The common uses are summarized as follows:

'''
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              # 调用者模块层调用该函数所在的行号
'''

Guess you like

Origin blog.csdn.net/weixin_55629186/article/details/134712002