Генши: Не удается получить доступ к импортированным модулям из директив в HTML
Справочная информация: я использую Genshi для создания отчетов в формате HTML.
import genshi
import os
from genshi.template import MarkupTemplate
files = [
r"a\b\c.txt",
r"d/e/f.txt",
]
html = '''
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/">
<head>
</head>
<body>
<p py:for="f in sorted(files, key=lambda x: x.lower().split(os.path.sep))">
${f}
</p>
</body>
</html>
'''
template = MarkupTemplate(html)
stream = template.generate(
files = files
)
print(stream.render('html'))
Проблема: Genshi генерирует исключение UndefinedError, потому что он не знает о модулях, которые я импортировал.
D:\SVN\OSI_SVT\0.0.0.0_swr65430\srcPy\OSI_SVT>python36 test.py
Traceback (most recent call last):
File "test.py", line 26, in <module>
print(stream.render('html'))
File "C:\Python36\lib\site-packages\genshi\core.py", line 184, in render
return encode(generator, method=method, encoding=encoding, out=out)
...
genshi.template.eval.UndefinedError: "os" not defined
Вопрос: Есть ли способ заставить Genshi автоматически узнавать об импортированных модулях?
Если это не возможно изначально в Genshi, я бы принял ответ, который программно создает коллекцию модулей, которые были импортированы, чтобы они могли быть переданы в generate()
вызов. Например: generate(**args)
Что я пробовал:
- Прочитайте документацию к Генши.
- Искал Stackru. Нет кости.
- Добавление
os = os
кtemplate.generate()
вызов. Это работает, но раздражает и подвержен ошибкам дублировать мой импорт.
1 ответ
Я нашел способ сделать это за пределами Genshi. Этот подход добавляет все глобальные и локальные объекты (импорт, а также глобальные и локальные переменные) и добавляет их в словарь. Затем словарь передается generate()
как ключевые слова args (см. этот ответ, если вы не знакомы с этим).
import genshi
import os
import types
from genshi.template import MarkupTemplate
html = '''
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/">
<head>
</head>
<body>
<p py:for="f in sorted(files, key=lambda x: x.lower().split(os.path.sep))">
${f}
</p>
</body>
</html>
'''
def main():
files = [
r"a\b\c.txt",
r"d/e/f.txt",
]
generation_args = {}
for scope in [globals(), locals()]:
for name, value in scope.items():
generation_args[name] = value
template = MarkupTemplate(html)
stream = template.generate(**generation_args)
print(stream.render('html'))
main()