推荐学习书目
› Learn Python the Hard Way
Python Sites
› PyPI - Python Package Index
› http://diveintopython.org/toc/index.html
› Pocoo
值得关注的项目
› PyPy
› Celery
› Jinja2
› Read the Docs
› gevent
› pyenv
› virtualenv
› Stackless Python
› Beautiful Soup
› 结巴中文分词
› Green Unicorn
› Sentry
› Shovel
› Pyflakes
› pytest
Python 编程
› pep8 Checker
Styles
› PEP 8
› Google Python Style Guide
› Code Style from The Hitchhiker's Guide
zerh925
V2EX  ›  Python

[python]能知道函数的外层调用函数吗?

  •  
  •   zerh925 · May 21, 2015 · 3797 views
    This topic created in 4188 days ago, the information mentioned may be changed or developed.
    def foo():
        print 'foo'
    
    def bar():
        foo()
    
    def run():
        foo()
    

    我有办法知道知道foo()每次是被什么函数调用吗?

    比如被bar()调用和被run()调用做不同的操作。

    或者我能知道foo()每次被调用是程序运行以来第几次运行吗?自省能做到这些吗?

    17 replies  •  2015-05-22 08:53:18 +08:00
    Septembers
    Septembers
    May 21, 2015
    1
    不能
    (理论可以通过动态分析bytecode完成(恩 我没测试过
    arbipher
    arbipher
    May 21, 2015❤️1
    2
    被什么函数调用可以知道,参考
    https://docs.python.org/2/library/inspect.html
    http://stackoverflow.com/questions/900392/getting-the-caller-function-name-inside-another-function-in-python

    第几次被调用据我所知没有,等大神来回答吧。你加个count或者用闭包试试。
    vicalloy
    vicalloy
    May 21, 2015
    3
    我觉得你还是给foo加个参数吧
    zerh925
    zerh925
    OP
    May 21, 2015
    4
    刚dir了一下任意函数,发现一个func_name属性。通过传这个参数给foo()算是实现了。
    ```python
    def foo(outer):
    print "I was called by ", outer

    def bar():
    foo(bar.func_name)

    def run():
    foo(run.func_name)
    ```

    还有更好的办法吗?
    9hills
    9hills
    May 21, 2015❤️1
    5
    https://gist.github.com/ninehills/9917858

    不仅能知道是谁调用的,还会打印出调用链。debug用
    zerh925
    zerh925
    OP
    May 21, 2015
    6
    @arbipher 感谢!非常有用!刚在打自己的答案
    9hills
    9hills
    May 21, 2015❤️1
    7
    效果如下:
    $ python test.py
    2014-04-02 00:40:44,273 [test.py:main() --> test.py:test('aaa')] hahha aaa
    muzuiget
    muzuiget
    May 21, 2015❤️1
    8
    可以的,用这个模块 https://docs.python.org/2/library/traceback.html

    我最常用的

    import traceback; traceback.print_stack()

    打印当前的调用栈,其实就是相当于出现错误时的信息。
    songco
    songco
    May 21, 2015
    9
    支持stacktrace的都可以把...
    recall704
    recall704
    May 21, 2015
    10
    就二楼哪个方法吧,之前也是用的那个方式.
    alexapollo
    alexapollo
    May 21, 2015❤️2
    11
    每个语言的月经贴。记住关键字:stacktrace/backtrace,加上语言python/c/java,google一搜就有。

    授人以渔!
    monkeylyf
    monkeylyf
    May 21, 2015
    12
    >>> import inspect
    >>> inspect.stack()
    staticor
    staticor
    May 21, 2015❤️1
    13
    我以前在leetcode还是codewars好像见过类似的统计函数被第几次调用的 提供一个可能有帮助的代码

    ![](http://7xivqr.com1.z0.glb.clouddn.com/15-5-21/88924102.jpg)
    WKPlus
    WKPlus
    May 21, 2015❤️1
    15
    查找caller上面很多人说过了,我用过一个方法来统计这个函数被调用多少次:

    def foo(called=[0]):
    called[0] += 1 # called[0]记录了foo被调用了多少次
    #your code here


    总算发现了python函数default值这个坑的第二个用法了:)

    当然也可以用函数属性来完成这个工作,不过要在foo函数定义之外再初始化一次这个属性,感觉没上面的代码好玩~
    zerh925
    zerh925
    OP
    May 22, 2015
    16
    @WKPlus nice trick!
    jedihy
    jedihy
    May 22, 2015
    17
    几乎所有语言都能打调用栈啊
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   880 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 41ms · UTC 23:47 · PVG 07:47 · LAX 15:47 · JFK 18:47
    ♥ Do have faith in what you're doing.