পাইথনে কলিং ফাংশনের মডিউলটির __ নাম__ পান


98

ধরা যাক myapp/foo.py:

def info(msg):
    caller_name = ????
    print '[%s] %s' % (caller_name, msg)

এবং myapp/bar.pyএতে রয়েছে:

import foo
foo.info('Hello') # => [myapp.bar] Hello

আমি এক্ষেত্রে কলিং ফাংশনগুলির মডিউল (যা 'মাই্যাপ.ফু') caller_nameএর __name__বৈশিষ্ট্যে সেট হতে চাই । কিভাবে এই কাজ করা যেতে পারে?


ধরে নিন যে অন্য কোনও এন্ট্রি পয়েন্ট স্ক্রিপ্ট বার.পিকে আহ্বান জানায় .. এবং এভাবে caller_nameহতে পারে না__main__
শ্রীধর রত্নাকুমার

উত্তর:


125

পরিদর্শন মডিউলটি দেখুন:

inspect.stack() স্ট্যাকের তথ্য ফিরিয়ে দেবে।

কোনও ফাংশনের অভ্যন্তরে, inspect.stack()[1]আপনার কলারের স্ট্যাক ফিরিয়ে দেবে। সেখান থেকে আপনি কলারের ফাংশনটির নাম, মডিউল ইত্যাদি সম্পর্কে আরও তথ্য পেতে পারেন

বিশদ জন্য ডক্স দেখুন:

http://docs.python.org/library/inspect.html

এছাড়াও, ডগ হেলম্যানের তার পিএমওটিডাব্লু সিরিজে পরিদর্শন মডিউলটির একটি সুন্দর রচনাআপ রয়েছে:

http://pymotw.com/2/inspect/index.html#module-inspect

সম্পাদনা: এখানে কিছু কোড যা আপনি যা চান তা করে, আমি মনে করি:

import inspect 

def info(msg):
    frm = inspect.stack()[1]
    mod = inspect.getmodule(frm[0])
    print '[%s] %s' % (mod.__name__, msg)

4
সুতরাং আপনি __name__মডিউলটি ব্যবহার করে এই মডিউলটির বৈশিষ্ট্যটি কীভাবে পাবেন inspect? উদাহরণস্বরূপ, আমি আমার উপরের উদাহরণে কীভাবে ফিরে পাব myapp.foo(না myapp/foo.py)? আমি ইতিমধ্যে এসওতে পোস্ট করার আগে পরিদর্শন মডিউলটি ব্যবহার করার চেষ্টা করেছি।
শ্রীধর রত্নকুমার

6
সচেতন থাকুন যে এটি আমদানি হুকগুলির সাথে অদ্ভুতভাবে মিথস্ক্রিয়া করবে, আয়রনপথিতে কাজ করবে না এবং জাইথনে বিস্ময়কর উপায়ে আচরণ করতে পারে। আপনি যদি এইভাবে যাদু এড়াতে পারেন তবে এটি সেরা।
গ্লিফ

4
আরও মনে রাখবেন যে স্ট্যাক ফ্রেমের একটি রেফারেন্স রাখা পাইথনের জিসিকে সঠিকভাবে কাজ করতে বাধা দিতে পারে। সতর্কতা এখানে দেখুন: docs.python.org/library/inspect.html#the-interpreter-stack
কামিল

6
মনে রাখবেন যে যদি কলার ফাংশনটি সাজানো থাকে (@ ...), আপনাকে inspect.stack()[2]প্রকৃত কলারের জন্য অ্যাক্সেস করতে হবে ।
আমির আলী আকবরী

এছাড়াও নোট করুন যে আপনি যখন পাইথানস্টলার ব্যবহার করে আপনার পাইথন কোডটি একটি এক্সে রূপায়িত করেন তখন এই যুক্তিটি সঠিকভাবে কাজ করতে ব্যর্থ হয়।
পানোফিশ

19

একই ধরণের সমস্যার মুখোমুখি হয়ে আমি জানতে পেরেছি যে সিস মডিউল থেকে sys._current_frames () তে অন্তত সুনির্দিষ্ট ব্যবহারের ক্ষেত্রে পরিদর্শন আমদানির প্রয়োজন ছাড়াই আপনাকে সহায়তা করতে পারে এমন আকর্ষণীয় তথ্য রয়েছে।

>>> sys._current_frames()
{4052: <frame object at 0x03200C98>}

তারপরে আপনি f_back ব্যবহার করে "উপরে উঠতে" পারেন:

>>> f = sys._current_frames().values()[0]
>>> # for python3: f = list(sys._current_frames().values())[0]

>>> print f.f_back.f_globals['__file__']
'/base/data/home/apps/apricot/1.6456165165151/caller.py'

>>> print f.f_back.f_globals['__name__']
'__main__'

উপরের মার্ক রডির পরামর্শ অনুসারে ফাইলের নামের জন্য আপনি f.f_back.f_code.co_filename ব্যবহার করতে পারেন। আমি এই পদ্ধতির সীমাবদ্ধতা এবং সতর্কতা সম্পর্কে নিশ্চিত নই (একাধিক থ্রেড সম্ভবত সমস্যা হতে পারে) তবে আমি আমার ক্ষেত্রে এটি ব্যবহারের ইচ্ছা করি।


4
দ্রষ্টব্য: পাইপ স্ট্রোলার ব্যবহার করে এক্সপি করতে সংকলনের পরে পরিদর্শন.স্ট্যাক কোডটি ব্যর্থ হয়, তবে sys._current_frames ওয়ার্কস ফাইন ব্যবহার করে ... সুতরাং এটি আমার পক্ষে পছন্দসই কৌশল।
প্যানোফিশ

7
আমি মনে করি sys._getframe(1)কল করার পরিবর্তে আগের ফ্রেমটি পাওয়া আরও সহজ sys._current_frames()(বিটিডব্লিউ যা প্রতিটি থ্রেডের জন্য ফ্রেম ম্যাপিং দেয়)।
হুবলি

আপনাকে হুবলি ধন্যবাদ, আমি এখনও এটি পরীক্ষা করে দেখিনি তবে বহু-থ্রেডেড পরিস্থিতিতে খুব দরকারী বলে মনে হচ্ছে।
লুই LC

আমি inspect.currentframe()পরিবর্তে ব্যবহার করতে পছন্দ করি sys._current_frames().values()[0]
অরণ-ফে

3

আমি এটি করার পরামর্শ দিচ্ছি না, তবে আপনি নিম্নলিখিত পদ্ধতিটি দিয়ে আপনার লক্ষ্যটি অর্জন করতে পারেন:

def caller_name():
    frame=inspect.currentframe()
    frame=frame.f_back.f_back
    code=frame.f_code
    return code.co_filename

তারপরে আপনার বিদ্যমান পদ্ধতিটি নিম্নরূপ আপডেট করুন:

def info(msg):
    caller = caller_name()
    print '[%s] %s' % (caller, msg)

7
ফাইলের __name__
নামটি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.