2012-08-03 31 views
7

Tôi muốn nhận thông tin về người gọi của một chức năng cụ thể trong python. Ví dụ:Nhận thông tin người gọi chức năng trong python

class SomeClass(): 
    def __init__(self, x): 
     self.x = x 
    def caller(self): 
     return special_func(self.x) 

def special_func(x): 
    print "My caller is the 'caller' function in an 'SomeClass' class." 

Có thể với python không?

Trả lời

10

Có, chức năng sys._getframe() cho phép bạn truy xuất khung từ ngăn xếp thực thi hiện tại, sau đó bạn có thể kiểm tra bằng các phương pháp và tài liệu được tìm thấy trong inspect module; bạn sẽ được tìm kiếm người dân địa phương cụ thể trong các thuộc tính f_locals, cũng như đối với các thông tin f_code:

import sys 
def special_func(x): 
    callingframe = sys._getframe(1) 
    print 'My caller is the %r function in a %r class' % (
     callingframe.f_code.co_name, 
     callingframe.f_locals['self'].__class__.__name__) 

Lưu ý rằng bạn sẽ cần phải thực hiện một số dịch vụ chăm sóc để phát hiện những loại thông tin bạn tìm thấy trong mỗi khung.

+2

Từ các tài liệu: 'Nó không được đảm bảo để tồn tại trong tất cả các triển khai của Python.' – pradyunsg

3

Một ví dụ:

def f1(a): 
    import inspect 
    print 'I am f1 and was called by', inspect.currentframe().f_back.f_code.co_name 
    return a 

def f2(a): 
    return f1(a) 

sẽ lấy lại "ngay lập tức" người gọi.

>>> f2(1) 
I am f1 and was called by f2 

Và nếu không được gọi từ một bạn nhận được (trong IDLE):

>>> f1(1) 
I am f1 and was called by <module> 
+0

Cảm ơn bạn, Tôi đã có thể thực hiện việc này và điều chỉnh nó theo nhu cầu của tôi. –

2

Nhờ Jon Clements câu trả lời tôi đã có thể làm cho một hàm trả về một danh sách đặt hàng của tất cả những người gọi:

def f1(): 
    names = [] 
    frame = inspect.currentframe() 
    ## Keep moving to next outer frame 
    while True: 
     try: 
      frame = frame.f_back 
      name = frame.f_code.co_name 
      names.append(name) 
     except: 
      break 
    return names 

và khi gọi trong một chuỗi:

def f2(): 
    return f1() 

def f3(): 
    return f2() 

def f4(): 
    return f3() 

print f4() 

trông như thế này:

['f2', 'f3', 'f4', '<module>'] 

Trong trường hợp của tôi, tôi lọc ra bất cứ điều gì ở '<module>' và sau đó, và sau đó lấy mục cuối cùng là tên của người gọi có nguồn gốc.

Hoặc sửa đổi vòng lặp ban đầu để giải cứu tại sự xuất hiện đầu tiên của tên bất kỳ bắt đầu với '<':

frame = frame.f_back 
name = frame.f_code.co_name 
if name[0] == '<': 
    break 
names.append(name) 
Các vấn đề liên quan