Problème d’encodage à l’écriture

Encore et toujours...

Le problème exposé dans ce sujet a été résolu.

Bonjour,

L’encodage est vraiment quelque chose qui me fait perdre la tête. :colere:

Voici ce que je fais :

  • j’ouvre un fichier JSON en utf-8 avec :
with open(file, "r", encoding="utf-8") as opened_file:
  • j’importe ensuite les données avec json.load() comme ceci :
data = json.load(opened_file, object_pairs_hook=OrderedDict)
  • les données sont enduites lues dans plein de classes, fin le programme fait son taf

  • jusqu’au moment où je dois écrire dans un fichier qui doit utiliser l’encodage cp1252, là c’est le drame. Voici ce que je fais :

with open(path, "w", encoding="cp1252") as util_file:
    # j’ecris classiquement dans mon fichier avec .write()

Sans surprise j’ai des erreurs d’encodage ('charmap' codec can’t encode character '\u200e'). J’ai essayé de mettre des decode() et encode() partout, rien à faire…

Comment régler ce problème ? J’aimerais tellement tout faire en UTF8 mais pas moyen…

Merci à vous !

+0 -0

Merci à vous deux pour vos messages, ils commencent à me mettre sur la bonne voie. En effet, je pense qu’il s’agit d’un caractère un peu bizarre qui doit traîner dans mon fichier car en faisant un essai chez moi avec le fichier suivant que j’ai écrit pour le test :

{
  "path": "je_suis_un_fichier_pdf_vérifié.pdf",
  "name": "Un fichier PDF vérifié."
}

Et le code suivant (qui fait en gros la même chose que mon code au bureau) :

with open("test.json", "r", encoding="utf-8") as file:
    data = json.load(file, object_pairs_hook=OrderedDict)

with open("res.tex", "w", encoding="cp1252") as file:
    href = "\\href{{{}}}{{{}}}".format(data["path"], data["name"])
    file.write(href)

Tout s’est déroulé sans problème.

Ma question est donc comment est-ce que je retrouve ce caractère qui m’embête ? J’imagine que ça doit être un caractère invisible ou qui ressemble fortement à un autre car je n’ai rien remarqué de spécial. Aller au cas par cas ? (Je supprime le texte au fur à mesure jusqu’à ce que je trouve l’erreur)

Merci encore !

+0 -0

Je vois deux manières assez similaires de résoudre le problème, qui feront toutes deux appel à la méthode encode des chaînes de caractères.

La première est d’ouvrir ton fichier de sortie en mode binaire (wb) et donc sans préciser d’encodage. Tu feras donc des write d’objets bytes, que tu auras préalablement obtenu en convertissant ta chaîne avec encode et en choisissant le bon encodage. La méthode encode possède un paramètre errors auquel tu peux préciser comment tu veux que les erreurs d’encodage soient traitées. Dans ton cas le plus judicieux serait replace ou ignore.
Ainsi tu pourrais faire util_file.write(data.encode('cp1252', errors='ignore')).

L’autre solution est assez similaire sauf que tu continues d’ouvrir ton fichier en mode texte avec le bon encodage. Tu encodes/décodes juste tes chaînes pour appliquer la même opération que précédemment : data = data.encode('cp1252', errors='ignore').decode('cp1252').

Pour info, le caractère \u200e est le caractère LEFT-TO-RIGHT MARK donc il est invisible et supprimable.

amael

… ou pas, si tu supprime ça dans un texte multilingue avec des langues qui s’écrivent dans différentes directions, tu vas avoir des problèmes d’affichage.

Cela dit, aucune langue qui s’écrit de droite à gauche ne peut être représentée avec windows-1252/cp1252. Donc ça me fait dire que quelque part tu essaie de faire quelque chose d’impossible.

Tu as un exemple du texte que tu essaie de convertir ?

@entwanne, j’essaierais ça demain quand j’aurais le code sous les yeux, merci à toi !

L’exemple que j’ai écrit ci-dessus est exactement ce que je souhaite convertir, un JSON encodé en utf-8 avec du texte français (donc des accents). Mon tuteur m’a envoyé un pavé JSON qu’il a généré en convertissant du CSV en JSON que j’ai ensuite copié collé dans mes fichiers. Le caractère à du apparaître lors de toutes ces étapes. Un coup de strip("\u200e") et on en parle plus je pense non ?

Non, la méthode strip() n’enlève que les occurrences situées au début ou à la fin d’une chaine. "axxxaxxxa".strip('a') == 'xxxaxxx'. Dans ce cas, je dirais plutôt quelque chose comme ''.join([char for char in "axxxaxxxa" if char != "a"]) == 'xxxxxx'. Cela dit, comme le dit SpaceFox, vérifie bien que le reste de ta chaine est normal. Si ce caractère est apparu suite à une erreur dans la gestion des encodages, il n’est peut-être pas le seul.

+0 -0

Je me suis complètement fourvoyé, excusez-moi. Le bug ne vient pas du tout du JSON mais des données importées depuis une base de donnée Excel. J’inclus en effet un peu plus de 50 000 identifiant de pièces (suite de lettres et de chiffres) depuis un fichier Excel. En faisant un petit test avec Python, je découvre que sur ces 50 000 données environs, trois présentent ce caractère qui n’a rien à faire là.

En effet, ce n’est pas la méthode strip() au quel je pensais mais à la méthode replace(), ce qui a complément corrigé mon problème.

Avec toute cette histoire, je me sens déjà un peu plus à l’aise avec les encodages, merci à vous ! :D

ÉDIT : il n’y aurait pas une méthode python pour retirer tous les caractères spéciaux d’une chaîne de caractères ? Un identifiant de pièces n’a pas à avoir de caractères spéciaux, c’est comme un code barre.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte