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 字符串文字中开始一个转义序列。为防止这种情况,您大致有四种选择:

  1. 正确转义您的字符串。也就是说,将每个路径分隔符反斜杠加倍:'"G:\Shared drives\2 test\2021\08.2021\test.xlsx"'
  2. 使用原始字符串防止转义序列被解释:r'G:\Shared drives test21.2021\test.xls'
  3. 使用正斜杠代替反斜杠,作为 Windows 路径有效:'G:/Shared drives/2 test/2021/08.2021/test.xls'
  4. 不要在 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"