Как получить ту же функциональность, что и C __FUNCTION__ в Python? - PullRequest
4 голосов
/ 06 августа 2010

В C я могу поместить log printf внутри функции, подобной этой:

void xx_lock (int xx_flag)
{
  printf ("%s: START with %d\n", __FUNCTION__, xx_flag);
}

, поэтому я могу скопировать ту же строку, где мне нужно, в любую функцию, и она отобразит имя функции в журнале. Я хочу что-то подобное в Python. Но если я использую

__name__

также отображается имя модуля, а не имя функции.

def xxx_lock(xx_flag=0)
    sys.stdout.write("%s: START with %d\n" % (__name__, xx_flag))

Есть ли какая-нибудь простая конструкция, которую я могу использовать в этом примере, чтобы показать имя функции Python? Чтобы получить вывод, как это:

xxx_lock: START with 1

Отредактировано: добавлен параметр в пример.

Ответы [ 4 ]

9 голосов
/ 06 августа 2010

То, о чем вы просили, не может быть выполнено (приятно - есть способы сделать это, но они - неприятные хаки).НО: ты действительно не хочешь этого делать.Подумайте на более высоком уровне: вам нужен простой способ изменить функцию, чтобы регистрировать ее запуск.Изменение исходного кода функции не является хорошим способом сделать это - в конце концов, регистрация не имеет никакого отношения к тому, что делает функция!Вместо этого вы хотите изменить функцию ex post facto .

def startLog( func ):
    def loggedFunc( *args, **kwargs ):
        print( "starting {0} with {1}".format( func.__name__, args[ 0 ] ) )
        return func( *args, **kwargs )

    return loggedFunc

@startLog
def theFunc( ):
    print( "running theFunc" )

theFunc( )
# starting theFunc
# running theFunc

. Это пример Python декоратора : он преобразует функцию во время определенияв другой.Это синтаксический сахар для:

def theFunc( ):
    print( "running theFunc" )
theFunc = startLog( theFunc )

Другими словами, вы берете сам объект функции (помните - функции тоже являются объектами, вы можете передавать их, изменять, просматривать их атрибуты и т. Д.!) и переопределить его.Глядя на исходный код, мы видим, что startLog определяет новую функцию (loggedFunc), которая сначала печатает трассировку журнала, а затем запускает исходную функцию, передавая ее аргументы.Применение декоратора заменяет theFunc на loggedFunc, так что функция, связанная с именем theFunc, теперь регистрирует себя!

Имеет ли это смысл?Я рад объяснить это более подробно.

Редактировать

Как уже указывалось, это не дает конкретного ответа на ваш вопрос;если вам нужно больше функциональности, чем этот, то используйте модуль logging, который делает все, что вам когда-либо понадобится, а затем еще немного.Ходить по стеку просто неприлично и хрупко, хотя = p.

7 голосов
/ 06 августа 2010

katrielalex выше правильно, что вы не должны пытаться сделать это "путь C".В Python есть батарейки, так почему бы не использовать их?

import logging, sys

logging.basicConfig(format="%(filename)s:%(funcName)s:%(message)s",level=logging.DEBUG,stream=sys.stderr)

def testFunc():
    logging.debug("entering")

testFunc()
2 голосов
/ 06 августа 2010
import inspect
inspect.getframeinfo(inspect.currentframe()).function

Это обеспечивает функциональность, которая больше всего напоминает C __FUNCTION__, но, как сказал katrielalex, это взлом.Декоратор - лучшее решение в конце.

1 голос
/ 06 августа 2010
import inspect
def function_with_line(depth=1):
    stack = inspect.stack()
    frame = stack[depth][0]
    code = frame.f_code
    return "%s:%i" % (code.co_name, frame.f_lineno)

def foo():
    print "Currently in %s" % function_with_line()

Я не рекомендую использовать это из кода высокого уровня;вставьте его в логгер и увеличьте depth, чтобы получить имя правильного стекового фрейма.Также помните, что эта информация не будет доступна во всех реализациях Python.Это также может быть довольно медленным в некоторых реализациях Python;если для вас важна производительность журналирования, выполните соответствующий тест.

Возможно, вам лучше использовать logging, но если по какой-то причине это не вариант (например, интеграция в другую существующую систему журналирования), вот каксделай это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...