#python
#python
Вопрос:
Итак, я пишу несколько скриптов на python, которые помогут мне выполнить некоторые простые вычисления:
WireRadius = .455 / 1000 / 2 #m, 25AWG
CoilInnerRadius = 10.0 / 1000 / 2 #m
CoilOuterRadius = 20.0 / 1000 / 2 #m
CoilLength = 20.0 / 1000 #m
CoilVolume = 3.14 * (CoilOuterRadius**2 - CoilInnerRadius**2) * CoilLength #m^3
print "CoilVolume: " str(CoilVolume)
WireCrossSection = 3.14 * WireRadius**2 #m^2
print "WireCrossSection: " str(WireCrossSection)
LengthOfWire = CoilVolume / WireCrossSection / 2 #m
print "LengthOfWire: " str(LengthOfWire)
Теперь я хочу, чтобы скрипт распечатал все промежуточные компоненты, чтобы я мог видеть, что происходит. Если я облажаюсь, это также позволит мне точно определить строку, в которой моя математика неверна, потому что именно тогда числа становятся бессмысленными.
Однако это явно не очень СУХО, поскольку я выписываю имя каждой переменной не один и не два раза, а три раза:
LengthOfWire = CoilVolume / WireCrossSection / 2 #m
print "LengthOfWire: " str(LengthOfWire)
Если бы я вводил это в интерактивную оболочку, она автоматически выдавала бы мне значения промежуточных компонентов:
>>> LengthOfWire = CoilVolume / WireCrossSection / 2 #m
14.491003502
что довольно приятно, потому что оператор присваивания сохраняется, что означает, что я точно знаю, каково следующее значение. Однако проблема с его помещением в интерактивную оболочку заключается в том, что внесение изменений и повторный запуск всего скрипта (который занимает несколько десятков вычислений) утомительны. Есть ли какой-либо способ добиться этой функциональности в сценариях, запускаемых через python script.py ?
Ответ №1:
def debug(val):
logging.debug('DEBUG: %r', val)
return val
...
LengthOfWire = debug(CoilVolume / WireCrossSection / 2)
Не забудьте соответствующим образом настроить свой регистратор.
Ответ №2:
Улучшенная версия функции Игнасио:
import logging
def debug(val, label=None):
"""Prints a debug message consisting of a value and an optional label."""
if label is None:
logging.debug('DEBUG: %r', val)
else:
logging.debug('DEBUG: %s = %r', label, val)
return val
...
LengthOfWire = debug(CoilVolume / WireCrossSection / 2, label="Wire length")
Ответ №3:
Рассмотрите возможность использования pdb для мониторинга выполнения. Я сомневаюсь, что вам понадобятся все эти операторы ведения журнала после того, как вы отработали вычисление.
У Дуга Хеллманна есть хороший проработанный пример использования pdb.
Ответ №4:
Я думаю debug
, что функция, вероятно, лучшая, но если вы действительно хотите выполнять назначения, не скрывая выражения, это действительно возможно с помощью метаклассов:
class print_dict(dict):
def __setitem__(self, key, value):
if not key.startswith('_'):
print("{}: {}".format(key, value))
super().__setitem__(key, value)
class MetaPrint(type):
@classmethod
def __prepare__(metacls, name, bases):
return print_dict()
def __new__(cls, name, bases, classdict):
result = type.__new__(cls, name, bases, dict(classdict))
return result
def foo(x):
class ShowMe(metaclass=MetaPrint):
WireRadius = x / 1000 / 2 #m, 25AWG
CoilInnerRadius = 10.0 / 1000 / 2 #m
CoilOuterRadius = 20.0 / 1000 / 2 #m
CoilLength = 20.0 / 1000 #m
CoilVolume = 3.14 * (CoilOuterRadius**2 - CoilInnerRadius**2) * CoilLength #m^3
WireCrossSection = 3.14 * WireRadius**2 #m^2
LengthOfWire = CoilVolume / WireCrossSection / 2 #m
foo(.455)
Затем, когда вы все отсортируете, просто удалите class ShowMe...
строку и удалите тело класса. Основным ограничением этого является то, что вы не можете return
использовать его внутри тела класса, поэтому, если вам нужно возвращаемое значение, вам нужно будет присвоить ему имя и, например return ShowMe.LengthOfWire
, в конце.