#python #python-3.x
#питон #python-3.x
Вопрос:
Мой вопрос связан с пакетом расписания Дэна Бейдера. Насколько я понимаю, вы планируете вызовы функций. Это довольно просто, если вы определяете функцию в своем скрипте. Однако как насчет функций, которые создаются динамически с помощью exec() ? Есть ли какой-нибудь способ сделать их вызываемыми? Я продолжаю получать ошибки при попытке запланировать эти функции. Я признаю, что это, вероятно, не самая лучшая идея (возможно, даже не очень хорошая идея), но это только для POC, и мне все еще интересно, можно ли это сделать.
def buildJob(lang, repType, name, file='', recipient='', server = '', db='', path=''):
today = datetime.datetime.strftime(datetime.datetime.today(), '%m%d%Y%H%M%S')
filePath = f"{c.path}{name}-{today}".replace('\', '/')
filename = f'{name}-{today}.xlsx'
funcText = f"""
def {name}():
sql = ("{file}")
filePath = ("{filePath}")
engine = sa.create_engine(conString)
dat = pd.read_sql_query(sql, engine)
engine.dispose()
del engine
buildSpreadsheet(dat, filePath)
sendSpreadsheet("{recipient}", "{filePath}.xlsx", "{filename}")
"""
Затем у меня есть функция для захвата funcText и exec() его. Однако, когда я передаю это в расписание, он говорит, что аргумент должен быть вызываемым.
Любая помощь будет очень признательна!
Комментарии:
1. Вы пробовали
globals()['function_name']
?2. Почему вы делаете это вместо того, чтобы просто создать закрытие? Все «динамические» вещи кажутся простыми переменными, это не похоже на то, что фактический код функции является шаблонным.
3. В зависимости от варианта использования этот подход может обеспечить лучшие сообщения об ошибках, поскольку результирующая функция не определяется другой функцией. (
namedtuple
Класс изначально был определен аналогичным образом, создавая гигантскийclass
оператор, выполняемыйexec
. В конечном итоге она была повторно реализована на C для повышения производительности, но как POC, это не плохая отправная точка.)4. Что касается globals()[‘function_name’] , когда я пытаюсь это сделать, я получаю ключевую ошибку, в которой говорится, что имя функции не найдено … и это после exec() . Тем не менее, когда я выполняю шаги вручную в терминале, функция определенно есть
5. Где это
exec()
происходит? Если она находится внутри функции, она будет находиться в локальной области видимости.
Ответ №1:
Вы можете получить определенные функции с locals()
помощью и globals()
dict
s .
# in global scope
as_str = f"""
def foo():
print('foo')
"""
exec(as_str)
foo = globals()['foo']
foo()
# in function scope
def bar():
as_str = f"""
def baz():
print('baz')
"""
exec(as_str)
return locals()['baz']
baz = bar()
baz()
Кто-то может меня поправить, но создание динамической функции с exec
помощью кажется плохой идеей. Особенно, если входные данные не обрабатываются.