Jinja2 NativeTemplate 渲染带有双引号问题的字符串
Jinja2 NativeTemplate rendering strings with double quotes issue
我正在从 Postgres DB 中读取路径值(列类型 String)。
例如:
路径 | "G:\Shared drives test21.2021\test.xlsx"
问题是路径中的某些嵌套目录以整数开头(如上),Python 自动将其视为十六进制字符。
\2 转换为\x02。
\08(视为 \0)转换为 \x008
\2021(视为 \20)转换为 \x821
print(repr('"G:\Shared drives test21.2021\test.xlsx"'))
> '"G:\Shared drives\x02 test\x821\x008.2021\test.xlsx"'
如何阻止 Python 解释这些十六进制值,并将其视为原始字符串?
预期结果:
'"G:\Shared drives\2 test\2021\08.2021\test.xlsx"'
编辑:
看起来数据库端的值是正确的,当我阅读它时也是如此。
路径已损坏一旦我使用 Jinja2 NativeTemplate(特别是本机模板)渲染它。
import jinja2
env = jinja2.nativetypes.NativeEnvironment()
path = '"G:\Shared drives\2 test\2021\08.2021\test.xlsx"'
print(path)
> "G:\Shared drives test21.2021\test.xlsx"
t = env.from_string('{{ path }}')
result = t.render(path=path)
print(result) # result is broken
> G:\Shared drives test18.2021 est.xlsx
print(repr(result))
> 'G:\Shared drives\x02 test\x821\x008.2021\test.xlsx'
如果我从路径字符串中删除双引号,渲染输出有效:
path = 'G:\Shared drives\2 test\2021\08.2021\test.xlsx'
result = t.render(path=path)
print(result) # works without double quotes
> G:\Shared drives test21.2021\test.xlsx
更新:
问题来源是jinja的NativeEnvironment中的native_concat方法。
输入法returnsliteral_eval
try:
return literal_eval(out)
复制:
path = '"G:\Shared drives\2 test\2021\08.2021\test.xlsx"'
print(literal_eval(path))
> G:\Shared drives test18.2021 est.xlsx
print(repr(literal_eval(path)))
> 'G:\Shared drives\x02 test\x821\x008.2021\test.xlsx'
\
在 Python 字符串文字中开始一个转义序列。为防止这种情况,您大致有四种选择:
- 正确转义您的字符串。也就是说,将每个路径分隔符反斜杠加倍:
'"G:\Shared drives\2 test\2021\08.2021\test.xlsx"'
- 使用原始字符串防止转义序列被解释:
r'G:\Shared drives test21.2021\test.xls'
- 使用正斜杠代替反斜杠,作为 Windows 路径有效:
'G:/Shared drives/2 test/2021/08.2021/test.xls'
- 不要在 Python 代码中使用字符串文字;相反,从其他来源(例如用户输入或文件)读取字符串。
s = "C:\Program Files\norton\appx"
打印
s = r"C:\Program Files\norton\appx"
打印
我已经向 Jinja 提出了这个问题,并得到了以下答复:
https://github.com/pallets/jinja/issues/1518#issuecomment-950326763
"这是由于解析 Python 字符串时转义的工作方式所致。您需要加倍 \\"
确实,将反斜杠加倍就可以了:
path = '"G:\\Shared drives\\2 test\\2021\\08.2021\\test.xlsx"'
print(literal_eval(path))
# output:
> G:\Shared drives test21.2021\test.xlsx
如果我想保留双引号:
path = '"\"G:\\Shared drives\\2 test\\2021\\08.2021\\test.xlsx\""'
print(literal_eval(path))
# output
> "G:\Shared drives test21.2021\test.xlsx"
我正在从 Postgres DB 中读取路径值(列类型 String)。
例如: 路径 | "G:\Shared drives test21.2021\test.xlsx"
问题是路径中的某些嵌套目录以整数开头(如上),Python 自动将其视为十六进制字符。
\2 转换为\x02。 \08(视为 \0)转换为 \x008 \2021(视为 \20)转换为 \x821
print(repr('"G:\Shared drives test21.2021\test.xlsx"'))
> '"G:\Shared drives\x02 test\x821\x008.2021\test.xlsx"'
如何阻止 Python 解释这些十六进制值,并将其视为原始字符串?
预期结果:
'"G:\Shared drives\2 test\2021\08.2021\test.xlsx"'
编辑: 看起来数据库端的值是正确的,当我阅读它时也是如此。
路径已损坏一旦我使用 Jinja2 NativeTemplate(特别是本机模板)渲染它。
import jinja2
env = jinja2.nativetypes.NativeEnvironment()
path = '"G:\Shared drives\2 test\2021\08.2021\test.xlsx"'
print(path)
> "G:\Shared drives test21.2021\test.xlsx"
t = env.from_string('{{ path }}')
result = t.render(path=path)
print(result) # result is broken
> G:\Shared drives test18.2021 est.xlsx
print(repr(result))
> 'G:\Shared drives\x02 test\x821\x008.2021\test.xlsx'
如果我从路径字符串中删除双引号,渲染输出有效:
path = 'G:\Shared drives\2 test\2021\08.2021\test.xlsx'
result = t.render(path=path)
print(result) # works without double quotes
> G:\Shared drives test21.2021\test.xlsx
更新:
问题来源是jinja的NativeEnvironment中的native_concat方法。
输入法returnsliteral_eval
try:
return literal_eval(out)
复制:
path = '"G:\Shared drives\2 test\2021\08.2021\test.xlsx"'
print(literal_eval(path))
> G:\Shared drives test18.2021 est.xlsx
print(repr(literal_eval(path)))
> 'G:\Shared drives\x02 test\x821\x008.2021\test.xlsx'
\
在 Python 字符串文字中开始一个转义序列。为防止这种情况,您大致有四种选择:
- 正确转义您的字符串。也就是说,将每个路径分隔符反斜杠加倍:
'"G:\Shared drives\2 test\2021\08.2021\test.xlsx"'
- 使用原始字符串防止转义序列被解释:
r'G:\Shared drives test21.2021\test.xls'
- 使用正斜杠代替反斜杠,作为 Windows 路径有效:
'G:/Shared drives/2 test/2021/08.2021/test.xls'
- 不要在 Python 代码中使用字符串文字;相反,从其他来源(例如用户输入或文件)读取字符串。
s = "C:\Program Files\norton\appx"
打印
s = r"C:\Program Files\norton\appx"
打印
我已经向 Jinja 提出了这个问题,并得到了以下答复: https://github.com/pallets/jinja/issues/1518#issuecomment-950326763
"这是由于解析 Python 字符串时转义的工作方式所致。您需要加倍 \\"
确实,将反斜杠加倍就可以了:
path = '"G:\\Shared drives\\2 test\\2021\\08.2021\\test.xlsx"'
print(literal_eval(path))
# output:
> G:\Shared drives test21.2021\test.xlsx
如果我想保留双引号:
path = '"\"G:\\Shared drives\\2 test\\2021\\08.2021\\test.xlsx\""'
print(literal_eval(path))
# output
> "G:\Shared drives test21.2021\test.xlsx"