কল পদ্ধতিতে কলারের পদ্ধতির নাম কীভাবে পাবেন?


182

পাইথন: কল পদ্ধতিতে কলারের পদ্ধতির নাম কীভাবে পাবেন?

ধরুন আমার 2 টি পদ্ধতি রয়েছে:

def method1(self):
    ...
    a = A.method2()

def method2(self):
    ...

আমি যদি পদ্ধতি 1 এর জন্য কোনও পরিবর্তন করতে না চাই, তবে পদ্ধতি 2 তে কলারের নাম কীভাবে পাওয়া যাবে (উদাহরণস্বরূপ, নামটি মেথড 1)?


3
হ্যাঁ. এখন আমি কেবলমাত্র পরীক্ষার জন্য কিছু ডকুমেন্টেশন সামগ্রী তৈরি করতে চাই।
zs2020

প্রযুক্তি একটি জিনিস, পদ্ধতিটি আরেকটি বিষয়।
zs2020

উত্তর:


228

ইন্সপেক্ট.জেটফ্রেমইনফো এবং অন্যান্য সম্পর্কিত ফাংশনগুলি inspectসহায়তা করতে পারে:

>>> import inspect
>>> def f1(): f2()
... 
>>> def f2():
...   curframe = inspect.currentframe()
...   calframe = inspect.getouterframes(curframe, 2)
...   print('caller name:', calframe[1][3])
... 
>>> f1()
caller name: f1

এই আত্মপরিচয়টি ডিবাগিং এবং উন্নয়নে সহায়তা করার উদ্দেশ্যে; উত্পাদন-কার্যকারিতা উদ্দেশ্যে এটির উপর নির্ভর করা ঠিক নয়।


18
"উত্পাদন-কার্যকারিতা উদ্দেশ্যে এটির উপর নির্ভর করা ঠিক নয়" " কেন না?
বেলটসোনটা

25
@ বেল্টসোনটা এটি সিপিথন বাস্তবায়নের উপর নির্ভরশীল, তাই আপনি যদি পাইপি বা জাইথন ​​বা অন্যান্য রানটাইম ব্যবহার করার চেষ্টা করেন তবে এটি ব্যবহার করে কোডটি ভেঙে যায়। এটি ঠিক আছে যদি আপনি কেবল স্থানীয়ভাবে বিকাশ এবং ডিবাগিং করেন তবে আপনার উত্পাদন সিস্টেমে এমন কিছু না যা আপনি চান।
রব্রু

@ ইউজেনক্রেভনেটস কেবল অজগর সংস্করণ ছাড়িয়ে আমি কেবল এটি নিয়ে একটি ইস্যুতে দৌড়েছি যেখানে এটি কোড তৈরি করে যা একবারে চালু হওয়ার একাধিক মিনিটে দ্বিতীয় রানের অধীনে চলে। এটি চূড়ান্তভাবে অক্ষম
দিমিত্রি

পাইথন 3 ডকুমেন্টেশনে এটি উল্লেখ করা হয়নি কেন? docs.python.org/3/library/inspect.html যদি তারা খারাপ হয় তবে তারা কমপক্ষে একটি সতর্কতা রাখবে?

1
এটি এমন লজ্জার বিষয় যে এটি পারফরম্যান্সে এমন হিট। লগিং এই জাতীয় (বা কলারমেমনারনেম ) এর সাথে খুব সুন্দর হতে পারে ।
স্টিংজি জ্যাক

92

সংক্ষিপ্ত সংস্করণ:

import inspect

def f1(): f2()

def f2():
    print 'caller name:', inspect.stack()[1][3]

f1()

(@ অ্যালেক্স এবং স্টিফান লিপ্পেনকে ধন্যবাদ সহ )


হ্যালো, আমি এটি চালানোর সময় আমি ত্রুটির নীচে পাচ্ছি: সোর্সফাইলে ফাইল না থাকলে ফাইল "/usr/lib/python2.7/inspect.py", 528 লাইন, লাইনটি [0] + ফাইল [-1]! = ' <> ': সূচিপত্র: স্ট্রিং সূচক সীমার বাইরে নয় আপনি দয়া করে পরামর্শ দিতে পারেন। অগ্রিম থ্যাঙ্কস
পুজোর

': KeyError: এই পদ্ধতির আমাকে একটি ত্রুটি দিলেন প্রধান '
Praxiteles

60

এটি ঠিক কাজ করে বলে মনে হচ্ছে:

import sys
print sys._getframe().f_back.f_code.co_name

1
এটি তার চেয়ে বেশি দ্রুত বলে মনে হচ্ছেinspect.stack
কেন্টওয়েট

তবুও এটি একটি সুরক্ষিত সদস্য ব্যবহার করে, যা সাধারণত পরামর্শ দেওয়া হয় না, কারণ sysমডিউলটি কিছু ভারী রিফ্যাক্টরিং পাওয়ার পরে এটি ব্যর্থ হতে পারে ।
ফিলিপ্রেম

28

আমি একটি সামান্য দীর্ঘ সংস্করণ নিয়ে এসেছি যা মডিউল এবং বর্গ সহ পুরো পদ্ধতির নাম তৈরির চেষ্টা করে।

https://gist.github.com/2151727 (রেভ 9cccbf)

# Public Domain, i.e. feel free to copy/paste
# Considered a hack in Python 2

import inspect

def caller_name(skip=2):
    """Get a name of a caller in the format module.class.method

       `skip` specifies how many levels of stack to skip while getting caller
       name. skip=1 means "who calls me", skip=2 "who calls my caller" etc.

       An empty string is returned if skipped levels exceed stack height
    """
    stack = inspect.stack()
    start = 0 + skip
    if len(stack) < start + 1:
      return ''
    parentframe = stack[start][0]    

    name = []
    module = inspect.getmodule(parentframe)
    # `modname` can be None when frame is executed directly in console
    # TODO(techtonik): consider using __main__
    if module:
        name.append(module.__name__)
    # detect classname
    if 'self' in parentframe.f_locals:
        # I don't know any way to detect call from the object method
        # XXX: there seems to be no way to detect static method call - it will
        #      be just a function call
        name.append(parentframe.f_locals['self'].__class__.__name__)
    codename = parentframe.f_code.co_name
    if codename != '<module>':  # top level usually
        name.append( codename ) # function or a method

    ## Avoid circular refs and frame leaks
    #  https://docs.python.org/2.7/library/inspect.html#the-interpreter-stack
    del parentframe, stack

    return ".".join(name)

দুর্দান্ত, এটি আমার লগিং কোডে আমার পক্ষে ভাল কাজ করেছে, যেখানে আমাকে বিভিন্ন স্থান থেকে ডেকে আনা যেতে পারে। অনেক ধন্যবাদ.
ছোট_বীরদী

1
stackআপনিও মুছে না ফেললে পরিদর্শন-
ankostis

এটি প্রমাণ করার জন্য আপনার কাছে কিছু টেস্ট কোড রয়েছে?
অ্যানাটোলি টেকটোনিক

1
একটি মন্তব্যে দেখাতে অসুবিধা ... কোনও সম্পাদককে এই ড্রাইভিং কোডটি কপি-পেস্ট করুন (মেমরি থেকে টাইপ করা) এবং আপনার কোডের উভয় সংস্করণ ব্যবহার করে দেখুন: `` `দুর্বল শ্রেণি সি আমদানি করুন: পাস ডিফ কিল (): মুদ্রণ ('হত্যা') ) ডিফ ফাঁস (): কলার_নাম () লোকাল_ভার = সি () দুর্বল নিহত `` `এবং না:` `` স্থানীয়_ভর অবশ্যই নিহত হয়েছে
k

1
অসাধারণ! অন্যান্য সমাধান ব্যর্থ হলে এটি কাজ করেছিল! আমি ক্লাসের পদ্ধতিগুলি এবং ল্যাম্বডা-এক্সপ্রেশনগুলি ব্যবহার করছি তাই এটি জটিল।
osta

16

আমি ব্যবহার করব inspect.currentframe().f_back.f_code.co_name। এর ব্যবহারটি পূর্বের উত্তরগুলির মধ্যে যা মূলত তিন ধরণের একটির মধ্যে অন্তর্ভুক্ত করা হয়নি:

  • কিছু পূর্ব উত্তর ব্যবহার করে inspect.stackতবে এটি খুব ধীর বলে জানা যায়
  • কিছু পূর্ব উত্তর ব্যবহার sys._getframe যা এর অভ্যন্তরীণ ব্যক্তিগত ফাংশন যা এর শীর্ষস্থানীয় আন্ডারস্কোর হিসাবে দেওয়া হয়, এবং তাই এর ব্যবহারটি স্পষ্টভাবে নিরুৎসাহিত করা হয়।
  • পূর্বের একটি উত্তর ব্যবহার করে inspect.getouterframes(inspect.currentframe(), 2)[1][3]তবে কী [1][3]অ্যাক্সেস করছে তা সম্পূর্ণ অস্পষ্ট ।
import inspect
from types import FrameType
from typing import cast


def caller_name() -> str:
    """Return the calling function's name."""
    # Ref: https://stackoverflow.com/a/57712700/
    return cast(FrameType, cast(FrameType, inspect.currentframe()).f_back).f_code.co_name


if __name__ == '__main__':
    def _test_caller_name() -> None:
        assert caller_name() == '_test_caller_name'
    _test_caller_name()

নোট যা cast(FrameType, frame)সন্তুষ্ট করতে ব্যবহৃত হয় mypy


Acknowlegement: একটি জন্য 1313e দ্বারা পূর্বে মন্তব্য উত্তর


10

উপরের জিনিসগুলির সংমিশ্রণে বিট। তবে এটি এখানে আমার ক্র্যাক।

def print_caller_name(stack_size=3):
    def wrapper(fn):
        def inner(*args, **kwargs):
            import inspect
            stack = inspect.stack()

            modules = [(index, inspect.getmodule(stack[index][0]))
                       for index in reversed(range(1, stack_size))]
            module_name_lengths = [len(module.__name__)
                                   for _, module in modules]

            s = '{index:>5} : {module:^%i} : {name}' % (max(module_name_lengths) + 4)
            callers = ['',
                       s.format(index='level', module='module', name='name'),
                       '-' * 50]

            for index, module in modules:
                callers.append(s.format(index=index,
                                        module=module.__name__,
                                        name=stack[index][3]))

            callers.append(s.format(index=0,
                                    module=fn.__module__,
                                    name=fn.__name__))
            callers.append('')
            print('\n'.join(callers))

            fn(*args, **kwargs)
        return inner
    return wrapper

ব্যবহার করুন:

@print_caller_name(4)
def foo():
    return 'foobar'

def bar():
    return foo()

def baz():
    return bar()

def fizz():
    return baz()

fizz()

আউটপুট হয়

level :             module             : name
--------------------------------------------------
    3 :              None              : fizz
    2 :              None              : baz
    1 :              None              : bar
    0 :            __main__            : foo

2
যদি অনুরোধ করা স্ট্যাকের গভীরতা প্রকৃতের চেয়ে বেশি হয় তবে এটি সূচিপত্র বাড়িয়ে তুলবে। modules = [(index, inspect.getmodule(stack[index][0])) for index in reversed(range(1, min(stack_size, len(inspect.stack()))))]মডিউল পেতে ব্যবহার করুন ।
jake77

1

আমি একটি উপায় খুঁজে পেয়েছি যদি আপনি ক্লাসগুলি জুড়ে চলে যান এবং ক্লাসটি পদ্ধতিটি এবং পদ্ধতির অন্তর্ভুক্ত চান তবে। এটি নিষ্কাশন কাজটি কিছুটা সময় নেয় তবে এটি তার পয়েন্ট করে। এটি পাইথন ২.7.১৩ এ কাজ করে।

import inspect, os

class ClassOne:
    def method1(self):
        classtwoObj.method2()

class ClassTwo:
    def method2(self):
        curframe = inspect.currentframe()
        calframe = inspect.getouterframes(curframe, 4)
        print '\nI was called from', calframe[1][3], \
        'in', calframe[1][4][0][6: -2]

# create objects to access class methods
classoneObj = ClassOne()
classtwoObj = ClassTwo()

# start the program
os.system('cls')
classoneObj.method1()

0
#!/usr/bin/env python
import inspect

called=lambda: inspect.stack()[1][3]

def caller1():
    print "inside: ",called()

def caller2():
    print "inside: ",called()

if __name__=='__main__':
    caller1()
    caller2()
shahid@shahid-VirtualBox:~/Documents$ python test_func.py 
inside:  caller1
inside:  caller2
shahid@shahid-VirtualBox:~/Documents$
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.