How to get all variable and method names used in script

前端 未结 4 1050
攒了一身酷
攒了一身酷 2020-12-25 08:54

It can be weird but I am looking for a way to get automatically all variables and method within a python script.

For example,

a = 1
b = 2
c = 3
myLis         


        
相关标签:
4条回答
  • 2020-12-25 09:16

    The ast module can do this fairly easily. If we assume the source is stored in a variable named source (could be read from a file):

    import ast
    
    root = ast.parse(source)
    names = sorted({node.id for node in ast.walk(root) if isinstance(node, ast.Name)})
    

    That loses ordering to gain uniquification and friendly display order, but you could just use a list comprehension or generator expression instead of a set comprehension if you don't need uniqueness but want ordering. The resulting list is:

    ['a', 'b', 'c', 'do_something', 'f', 'myList', 'range', 'someMethod', 'something', 'x']
    

    Unlike the other solutions posted so far, this will recurse into classes and functions to get the names used inside them, and doesn't require you to import the module or class to check, nor does it require you to implement recursive processing yourself; any syntactically valid Python code will work.

    Oddly, on Python 3 (substituting a valid print function call), you get:

     ['a', 'b', 'c', 'do_something', 'f', 'myList', 'print', 'range', 'someMethod', 'something']
    

    which adds print (as expected; it's a name now, not a keyword statement), but omits x. You didn't ask for x (the argument received by someMethod), and this doesn't produce it on Python 3. Names in function prototypes appear to not create a ast.Name node there, go figure. You can pull that info out of the ast.FunctionDef node from the arg attribute of each entry in the list node.args.args, but it's probably still not comprehensive; I suspect other definition related names might be missed, e.g. in class declarations with inheritance. You'd need to poke around with some examples to make sure you're checking everything (assuming you want stuff like x and want to work on Python 3).

    That said, x would show up just fine if you referenced it; if you passed it to do_something or used it in any way besides receiving and discarding it, it would show up.

    You can also make an effort to only handle names assigned to, not used (to exclude do_something, range) by extending the test to:

    names = sorted({node.id for node in ast.walk(root) if isinstance(node, ast.Name) and not isinstance(node.ctx, ast.Load)})
    

    But that will also drop someMethod (in both Py2 and Py3) because the definition itself doesn't produce an ast.Name, only the use of it does. So again, you'd have to delve a little deeper into the ast.Node internals for ast.FunctionDef, ast.ClassDef, etc. to get the names that aren't walk-ed directly.

    0 讨论(0)
  • 2020-12-25 09:24

    There are a lot of variables imported by python so you're going to get a long list, but vars() will work.

    a = 1
    b = 2
    c = 3
    myList = range(10)
    
    def someMethod(x): 
        something = 4
        return something
    
    f = someMethod(b)
    
    print vars()
    

    in terminal:

     $ python temp.py
    {'a': 1, 'c': 3, 'b': 2, 'myList': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 'f': 4, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'temp.py', '__package__': None, 'someMethod': <function someMethod at 0x10759b488>, '__name__': '__main__', '__doc__': None}
    

    EDIT
    You can clean it up a bit by checking for type of variables

    import types
    all_vars = dict(vars())
    for var_name, var in all_vars.iteritems():
        if type(var) not in [types.ModuleType, types.FunctionType] and not var_name.startswith("_"):
            print var_name
    

    in terminal:

    $ python temp.py
    a
    c
    b
    myList
    f
    
    0 讨论(0)
  • 2020-12-25 09:24

    You can use globals() function to get all the global names in your module, and since python has some global names by default like __builtins__ you can escape them :

    Since globals() return a dictionary contains the names and the values and builtin names have a format like __builtins__ you can filter them:

    >>> print([var for var in globals().keys() if '__' not in var])
    ['someMethod', 'c', 'b', 'a', 'myList']
    

    But note that it won't give you the local names inside the function like something. For that aim you can see inspect module https://docs.python.org/3/library/inspect.html#inspect.getmembers

    0 讨论(0)
  • 2020-12-25 09:26

    You can use dir() built-in for this. Suppose you save your file as test.py. You can do as follows:

    >>> import test
    
    >>> dir(test)
    ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'b', 'c', 'f', 'myList', 'someMethod']
    >>> 
    
    0 讨论(0)
提交回复
热议问题