Utilisation de caractères utf-8 dans un modèle Jinja2
J'essaie d'utiliser des caractères utf-8 lors du rendu d'un modèle avec Jinja2. Voici à quoi ressemble mon modèle:
<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
<meta charset="UTF-8">
<title>{{title}}</title>
...
La variable title est définie comme ceci:
index_variables = {'title':''}
index_variables['title'] = myvar.encode("utf8")
template = env.get_template('index.html')
index_file = open(preview_root + "/" + "index.html", "w")
index_file.write(
template.render(index_variables)
)
index_file.close()
Maintenant, le problème est que myvar est un message lu à partir d'une file d'attente de messages et peut contenir ces caractères utf8 Spéciaux (ex. "Séptimo Ciné").
Le modèle Rendu ressemble à quelque chose comme:
...
<title>Su00e9ptimo Cine</title>
...
Et je veux que ce soit:
...
<title>Séptimo Cine</title>
...
J'ai fait plusieurs tests mais je ne pouvez pas obtenir que cela fonctionne.
-
J'ai essayé de définir le titre de variable sans .encode ("utf8") , mais il lève une exception ( ValueError: attendu un objet bytes, pas un objet unicode ), donc je suppose que le message initial est unicode
J'ai utilisé chardet.detect pour obtenir l'encodage du message (c'est "ascii"), puis a fait ce qui suit: myvar.décoder("ascii").encoder ("cp852"), mais le titre n'est toujours pas rendu correctement.
Je me suis également assuré que mon modèle était un fichier UTF-8, mais cela n'a pas fait de différence.
Des idées sur la façon de le faire?
4 réponses
TL; DR:
-
passer Unicode à
template.render()
- coder le résultat unicode rendu dans une chaîne de caractères avant de l'écrire dans un fichier
Cela m'a laissé perplexe pendant un moment. Parce que vous le faites
index_file.write(
template.render(index_variables)
)
Dans une déclaration, c'est essentiellement une ligne où Python est concerné, donc le traceback que vous obtenez est trompeur: L'exception que j'ai obtenue lors de la recréation de votre cas de test ne s'est pas produite dans template.render(index_variables)
, mais dans index_file.write()
à la place. Donc diviser le code comme ce
output = template.render(index_variables)
index_file.write(output)
Était la première étape pour diagnostiquer où exactement le UnicodeEncodeError
se produit.
Jinja renvoie unicode whet vous le laissez rendre le modèle. Par conséquent, vous devez encoder le résultat d'un bytestring avant de pouvoir l'écrire dans un fichier:
index_file.write(output.encode('utf-8'))
La deuxième erreur est que vous passez un utf-8
codé bytestring à template.render()
- Jinja veut unicode. Donc, en supposant que votre myvar
contient UTF-8, vous devez d'abord le décoder en unicode:
index_variables['title'] = myvar.decode('utf-8')
Donc, pour tout dire ensemble, cela fonctionne pour moi:
# -*- coding: utf-8 -*-
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('myproject', 'templates'))
# Make sure we start with an utf-8 encoded bytestring
myvar = 'Séptimo Cine'
index_variables = {'title':''}
# Decode the UTF-8 string to get unicode
index_variables['title'] = myvar.decode('utf-8')
template = env.get_template('index.html')
with open("index_file.html", "w") as index_file:
output = template.render(index_variables)
# jinja returns unicode - so `output` needs to be encoded to a bytestring
# before writing it to a file
index_file.write(output.encode('utf-8'))
Essayez de changer votre commande de rendu à ceci...
template.render(index_variables).encode( "utf-8" )
La documentation de Jinja2 dit "cela renverra le modèle rendu en tant que chaîne unicode."
Http://jinja.pocoo.org/docs/api/?highlight=render#jinja2.Template.render
Espérons que cela aide!
Et si rien ne fonctionne parce que vous avez un mélange de langues - comme dans mon cas -, remplacez simplement "utf-8" par "utf-16"
Toutes les options d'encodage ici:
Ajoutez les lignes suivantes au début de votre script et cela fonctionnera correctement sans autres modifications:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding("utf-8")