génération de page HTML et pb d'encodage

codage windows notepad > html via python

a marqué ce sujet comme résolu.

Bonjour,

J'ai besoin de convertir en HTML une vingtaine de pages créées sous le notepad de windows.

J'ai écris un prog python (version 3.42) pour faire ça :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# -*- coding: utf-8 -*-
# Python v3.42
def importer(add_file_name):
    with open(add_file_name) as file : #avec encoding='cp1252' idem
        buffer = ""
#        print("codage du fichier add : ", file.encoding) >>> cp1252
        for line in file :
            buffer += line + '<br/>'
    return buffer

input_file_name = "f:/html/mes_projets/test_codage.html"
add_file_name = "f:/html/mes_projets/txt_accents.txt"
output_file_name = "f:/html/mes_projets/test_codage_result.html"

with open(input_file_name) as input_file:
    buffer = ""
    for line in input_file :
        if '<!--import-->' in line :
            buffer += importer(add_file_name)
        else :
            buffer += line
with open(output_file_name, "w") as output_file :
    output_file.write(buffer)

Le prog lit une page HTML de base, insère le fichier txt à l'emplacement marqué <!–import–> dans ce fichier HTML et écrit le tout dans une 2eme page html. Les deux pages html sont encodées utf-8 (vérifié sous pyCharm). Le fichier txt est encodé cp1252 selon le file.encoding de la fonction importer. Au final, la page html générée a bien les caractères accentués du html source, mais ceux du txt inséré sont remplacés par des '?'.

Je ne vois pas comment régler ce pb … (encoding="cp1252" dans open ne donne rien de plus)

html source :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head lang="fr">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
Texte dans la page HTML :
<br/><br/>
un texte à essayer : àéèùç
<br/><br/>
Texte importé de note-pad :
<br/><br/>
<!--import-->
</body>
</html>

fichier txt inséré :

1
2
texte généré sous note-pad :àéèùç
 et encore un peu àéèùç ...

page html générée :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head lang="fr">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
Texte dans la page HTML :
<br/><br/>
un texte à essayer : àéèùç
<br/><br/>
Texte importé de note-pad :
<br/><br/>
texte g�n�r� sous note-pad :�����
<br/> et encore un peu ����� ...<br/></body>
</html>

Une aide ?

Salut,

Je crois ne pas avoir tout compris à ce que tu nous décris là… M'enfin je vais tenter d'éclaircir quelques points :

  1. Quand tu parles de notepad, tu veux parler du bloc-notes de Windows, le fameux notepad.execrable ? Si c'est le cas, sache qu'il ne connait que l'encodage cp1252 (avec les locals françaises tout du moins).

  2. La fonction open, en mode texte, utilise par défaut l'encodage du système (donc le cp1252 dans ton cas). En considérant cela avec le point précédent, tu n'auras aucun problème pour ouvrir ton fichier texte… en mode texte avec l'encodage par défaut : with open(textfile) as file:.

  3. Une fois que tu as lu le fichier texte, tu obtiens une chaîne de caractère (objet str), encodée en utf-8 en interne de Python, mais ça on s'en fout. Toi, ce que tu veux c'est l'enregistrer dans ton fichier HTML en utf-8. Pour ça tu dois ouvrir ton fichier HTML en écriture avec l'encodage UTF-8 : with open(htmlfile, 'w', encoding='utf-8') as file:. Et tout ce que tu écriras dedans sera en utf-8. ;)

@psycopy :

Il s'agit bien du notepad.exe de windows et c'est bien encodé cp1252 … J'ai essayé avec encoding='cp1252' dans l'output, mais cette fois c'est les caractères accentués de ma page html initiale qui sont mal codés !!! :

1
2
3
4
5
6
7
8
Texte dans la page HTML :

un texte à essayer : à éèùç

Texte importé de note-pad :

texte généré sous note-pad :àéèùç
et encore un peu àéèùç ...

pour info, dans le debugger j'ai bien la variable line (lignes 8 et 9) de type str et non bytes, ce qui fait que je ne peux pas utiliser line.decode() inappliquable aux str

Et globalement, je ne comprends pas la logique de tout ça : mon fichier html d'entrée est en utf-8, python 3 travaille en interne en utf-8 pourquoi faut-il encoder en utf-8 en sortie plutôt que au niveau de l'input dans la fonction 'importer' ?

L'encodage par défaut utilisé par la fonction open est celui du système d'exploitation. Donc, le cp1252 sur les Windows avec les locals françaises. Si tu utilises Linux2 ce sera très probablement de l'UTF-8 par défaut.

Donc, si le fichier que tu lis ou que tu écris ne correspond pas à l'encodage par défaut de ton système, tu dois le préciser, par exemple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/env python3
# -*- coding:utf-8 -*-


HTML_TEXT = """<!DOCTYPE html>
<html>
<head lang="fr">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
Texte dans la page HTML :
<br/><br/>
un texte à essayer : àéèùç
<br/><br/>
Texte importé de note-pad :
<br/><br/>
{import_}
</body>
</html>
"""

INPUT_FILENAME = ...
INPUT_ENCODING = "utf-8" # ou "cp1252" ?

OUTPUT_FILENAME = ...
OUTPUT_ENCODING = "utf-8"


with open(OUTPUT_FILENAME, 'w', encoding=OUTPUT_ENCODING) as file_out:
    with open(INPUT_FILENAME, encoding=INPUT_ENCODING) as file_in:
        file_out.write(HTML_TEXT.format(import_=file_in.read()))

@psycopy : super ! :-) ça marche impec avec open(<fich html input>, encoding='utf8') en entrée html et la sortie html aussi avec encode='utf8'. Je pensais qu'à l'exec python, le codage utilisé était l'utf8 et pas le cp1252 sous windows.

La version qui complète qui marche :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# -*- coding: utf-8 -*-
# Python v3.42

def importer(add_file_name):
    with open(add_file_name) as file : #avec encoding='cp1252' idem
        buffer = ""
#        print("codage du fichier add : ", file.encoding) >>> cp1252
        for line in file :
            buffer += line + '<br/>'
    return buffer

input_file_name = "f:/html/mes_projets/test_codage.html"
add_file_name = "f:/html/mes_projets/txt_accents.txt"
output_file_name = "f:/html/mes_projets/test_codage_result.html"

with open(input_file_name, encoding='utf8') as input_file:
    buffer = ""
    for line in input_file :
        if '<!--import-->' in line :
            buffer += importer(add_file_name)
        else :
            buffer += line
with open(output_file_name, "w", encoding='utf8') as output_file :
    output_file.write(buffer)

Un trés grand merci …

+0 -0

Et bien si tu as résolu ton souci d'encodage, c'est parfais, maintenant tu vas pouvoir améliorer ton code pour le rendre un peu plus pythonic.

Par exemple, ta fonction importer qui te sert à lire un fichier texte et ajouter entre chaque ligne le tag <br/>, tu pourrais directement utiliser les méthodes str.join et file.readlines comme ceci : return '<br/>'.join(file.readlines())

Ou encore, la partie où tu concatènes le texte avec le html, tu peux utiliser la méthode str.replace directement pour remplacer la ligne que tu veux par le texte : html = html.replace('<!--import-->', text).

+0 -0

Hello,

Même si le sujet semble résolu, j'en profite pour partager un petit (enfin, c'est relatif) article (NSFW : le lien est clean mais si possible évitez la page d'accueil …) sur l'encoding en python (et n'hésitez pas a parcourir les autres articles, ce blog regorge de trucs et astuces géniaux - et pas qu'en python ;) )

Édit : Kje veille a la sécurité de nos lecteur :-°

Comme bien expliqué dans cet article, si vous vous refusez à consulter un blog de qualité parce que certaines photos/articles vous paraissent osés, le problème est peut-être au part. Donc éviter la page d'accueil au boulot, non, pas forcément, au pire ce ne sont que des gens nus.

Non, ce site n'est pas tout publique et la moindre des choses serait un message d'avertissement lorsque l'on débarque sans être loggé !

Je ne critique absolument pas le contenu du site, je pense même que c'est l'un des (LE ?) meilleurs blog francophone sur le langage Python. Et s'ils aiment mélanger le cul et la programmation, ça ne me dérange pas, mais ce n'est pas une raison pour ne pas prévenir. Je ne conseillerais jamais ce blog à des jeunes mineurs à cause de cet aspect du site. Et c'est vraiment dommage pour eux (les jeunes), parce qu'ils auraient beaucoup de choses à y découvrir sur le langage Python, même si le langage n'y est pas toujours très… châtié.

Maintenant, que sam&max fassent ce qu'ils veulent ne doit pas empêcher les gens qui proposent un lien vers leur blog de prévenir. ;)

+0 -0

J'étais allé sur le lien vers sam&max où on trouve effectivement souvent des choses intéressantes sur Python. Pour ce coup, ce qui me posait pb c'est que je croyais que l'interpréteur travaillait à l'exec en utf-8 et pas en cp1252 sous windows …

Pour le codage approximatif pas trop pythonesque, je suis d'accord, mais c'est un bout de code jetable aussi je n'ai pas cherché à optimiser, et de plus c'est un exemple pour caractériser le pb que j'avais, le vrai code est un peu plus compliqué … mais merci qd même, je ne pense pas à certaines focntions comme replace :-(

Pour ce coup, ce qui me posait pb c'est que je croyais que l'interpréteur travaillait à l'exec en utf-8 et pas en cp1252 sous windows …

rozo

Tu dois certainement confondre quelque chose. En interne, lorsque tu lis un fichier en mode texte, Python3 va effectivement convertir les données lus (les bytes qui forment le fichier) en UTF-8 pour les utiliser entant qu'objet str. Mais pour faire cette conversion, il a forcément besoin de connaître l'encodage d'origine de cet ensemble de bytes.

Par exemple, la chaîne de bytes en cp1252 qui représente la chaîne de caractères "éçà" sera b'\xe9\xe7\xe0', alors qu'en UTF-8 ce sera b'\xc3\xa9\xc3\xa7\xc3\xa0'. Si Python lis un fichier contenant cette chaîne de bytes encodée en UTF-8 alors que les locals de ton système lui disent que l'encodage par défaut est le cp1252, ça donnera un truc incompréhensible "éçÃ\xa0". Il faut donc impérativement dire à la fonction open que tu veux utiliser un encodage différent que celui de ton système.

[…] je ne pense pas à certaines focntions comme replace :-(

rozo

En fait, moi aussi j'y ai pensé un peu tard, si tu regarde la date de mon dernier edit… :-°

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