#1 Le 01/11/2020, à 11:51
- Compte supprimé
(Résolu) Aide pour modifier une ligne de script python
Bonjour,
Je voudrais modifier une ligne d'un fichier python, mais je n'y connais pas grand chose
Le script fabrique deux pages pdf, puis les assemble. Il les enregistre ensuite dans un fichier nommé "output.pdf
writer.addPage(pdf1.getPage(0))
writer.addPage(pdf2.getPage(0))
writer.write(open("output.pdf", "wb"))
Cela fait qu'à chaque exécution, le fichier output.pdf précédent est écrasé.
Je voudrais ajouter "le code qu'il faut" pour que le nom contienne une variable supplémentaire de façon à ne pas écraser le précédent.
Quelque chose du genre output1.pdf puis output2.pdf serrait suffisant.
Si quelqu'un peut m'aider, je le remercie d'avance.
Dernière modification par Compte supprimé (Le 01/11/2020, à 13:25)
#2 Le 01/11/2020, à 11:55
- pingouinux
Re : (Résolu) Aide pour modifier une ligne de script python
Bonjour,
Remplace "wb" par "ab".
Hors ligne
#3 Le 01/11/2020, à 12:01
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
Bonjour,
Ça ne répond pas à la question à mon avis. Ce que tu proposes, pingouinux, va concaténer et non pas créer des PDF indépendants (ce que semble vouloir Tamarou).
Si dans une boucle, une solution peut être la suivante où counter serait une variable contenant un entier, à initialiser quelque part dans le script.
counter += 1
outname = "output-{:d}.pdf".format(counter)
writer.write(open(outname, "wb"))
Hors ligne
#4 Le 01/11/2020, à 12:01
- Compte supprimé
Re : (Résolu) Aide pour modifier une ligne de script python
@pinguinux
Merci, mais cela ne change rien.
@beuguissime
Oui, c'est ce que je cherche à faire.
Je vais tester. Merci
Comment rentrer dans une boucle et en sortir ?
OU alors prendre le chiffre des secondes de l'heure de la création ?
Dernière modification par Compte supprimé (Le 01/11/2020, à 12:06)
#5 Le 01/11/2020, à 12:05
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
Si pas dans une boucle, il faut détecter le premier nom de fichier disponible. Si output-1.pdf existe, alors le script enregistre output-2.pdf. Si output-2.pdf, alors il faut utiliser output-3.pdf
C'est plus compliqué à faire.
Hors ligne
#6 Le 01/11/2020, à 12:08
- Compte supprimé
Re : (Résolu) Aide pour modifier une ligne de script python
Ou un chiffre aléatoire, il n'y a quelques occurences par jour.
#7 Le 01/11/2020, à 12:08
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
Ah oui avec un horodatage ce sera plus simple.
Ajoute en début
import time
et remplace la ligne avec "output.pdf" par ces deux lignes
outname = "output-{:d}.pdf".format(int(time.time()))
writer.write(open(outname, "wb"))
Il n'y aura pas de collisions si deux exécutions sont espacées d'au moins 1 seconde.
Hors ligne
#8 Le 01/11/2020, à 13:07
- pingouinux
Re : (Résolu) Aide pour modifier une ligne de script python
@beuguissime #3 : Tu as raison, j'ai mal lu la question…
Hors ligne
#9 Le 01/11/2020, à 13:14
- Compte supprimé
Re : (Résolu) Aide pour modifier une ligne de script python
Merci à vous deux.
Le code proposé par beuguissime fonctionne parfaitement. Maintenant je peux générer l'attestation dérogatoire de sortie de mon épouse et la mienne à la suite.
Un copier-coller sur le téléphone et c'est bon.
Bon dimanche, pas trop mauvais confinement
#10 Le 01/11/2020, à 14:12
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
Super si ça marche !
Ah mais faut faire profiter les copains et les copines des petits programmes qui facilitent la vie. Quel générateur d'attestation as-tu pris comme point de départ ?
Bon courage aussi pour les six semaines qui viennent (en espérant qu'elles suffisent pour inverser la tendance).
Hors ligne
#11 Le 01/11/2020, à 14:38
- Compte supprimé
Re : (Résolu) Aide pour modifier une ligne de script python
Voilà, c'est quelqu'un qui a parrtagé sur reddit.
https://github.com/Apoptoz/AttestationNumeriqueCOVID-19
Sur ma Arch, la police Arial est Arial.TTF et non Arial .ttf, j'ai dû modifier le generate_pdf.py en conséquence.
Et on peut faire mieux, car il y a les variables, quelque part dans le contexte, mais je ne sais pas les exploiter.
On pourrait ajouter le first_name au nom du fichier produit. Et ausi mettre la date/heure en clair et non avec son code.
Un truc comme : "Attestation-prénom-date-heure.pdf"
Si tu améliores, tu pourras lui proposer un commit !
EDIT : il y a autre chose : La date et l'heure de sortie sont bien affichées à leur place sur le qrcode, mais sur la page 1 c'est date et heure de rédaction. Mais le code semble bon
Dernière modification par Compte supprimé (Le 01/11/2020, à 16:25)
#12 Le 01/11/2020, à 14:40
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
Merci, je vais regarder.
Hors ligne
#13 Le 02/11/2020, à 16:26
- Compte supprimé
Re : (Résolu) Aide pour modifier une ligne de script python
Il reste la question de l'affichage de la date et heure de sortie sur le pdf.
Pour le nom du fichier généré, je laisse output.pdf dans la fonction qui fusionne les pdf.
Par contre, juste après il y a une fonction qui a bien toutes les données de l'attestation dans son contexte. J'utilise "shutil.move" pour modifier le nom du fichier produit. Il contient le prénom, l'heure et le motif.
Bien entendu, cela est fait par un ignorant en python, un peu en lisant, un peu en improvisant, donc certainement très maladroit.
Dernière modification par Compte supprimé (Le 02/11/2020, à 16:49)
#14 Le 02/11/2020, à 16:33
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
Alors essaye avec ça
outname = "Attestation-{:s}-{:s}-{:s}.pdf".format(last_name, first_name, leave_date)
writer.write(open(outname, "wb"))
(j'ai choisi l'ordre nom de famille-prénom)
Hors ligne
#15 Le 02/11/2020, à 16:39
- Compte supprimé
Re : (Résolu) Aide pour modifier une ligne de script python
J'ai déjà testé un truc dans ce genre, mais il ne connaît pas les données. Elles ne sont pas accessibles à cette fonction et je ne sais pas les ajouter
D'autre part, je lis et relis le script, mais je ne vois pas pourquoi sur le pdf il y a la date de rédaction et pas de sortie.
Dernière modification par Compte supprimé (Le 02/11/2020, à 16:41)
#16 Le 02/11/2020, à 16:51
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
Ah oui exact, désolé.
En plus de la modif au message n°14, il faut
remplacer (ligne 142)
def merge_pdfs()
par
def merge_pdfs(first_name, last_name, leave_date)
et remplacer (ligne 167)
merge_pdfs()
par
merge_pdfs(first_name, last_name, leave_date)
afin de transmettre les variables à la fonction de fusion de PDF.
Garde bien l'indentation.
Hors ligne
#17 Le 02/11/2020, à 16:55
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
Ligne 187 (je me réfère toujours à la numérotation sur la page Github), tu lis
qr_text = f"Cree le: {datetime.datetime.now().strftime('%d/%m/%Y a %H:%M')};\n"
Tu vois que ça ajoute le moment de génération (datetime.now()) dans la phrase “Crée le”. Est-ce bien de ça dont tu parles ?
(Arrgh, pas d'accent sur le premier e et pas d'espace insécable fine devant le deux-points. Sacrilège ! ) Ajout : C'est la faute du gouvernement apparemment.
Dernière modification par beuguissime (Le 02/11/2020, à 17:12)
Hors ligne
#18 Le 02/11/2020, à 16:58
- Compte supprimé
Re : (Résolu) Aide pour modifier une ligne de script python
Oui, c'est cela !
Le modèle officiel affiche la date / heure de sortie en bas du pdf et pas celle de création.
Par contre la date / heure de création est aussi dans le qr, c'est normal.
Dernière modification par Compte supprimé (Le 02/11/2020, à 17:01)
#19 Le 02/11/2020, à 17:11
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
Ah j'ai lu trop vite
En fait, tu parles sûrement des lignes de code 119 et 120
draw.text((205, 1416), datetime.datetime.now().strftime("%d/%m/%Y"), (0, 0, 0), font=font)
draw.text((535, 1416), datetime.datetime.now().strftime("%H:%M"), (0, 0, 0), font=font)
qui inscrivent quelque part sur le document la date et l'heure courante.
La ligne que je citais au n°17 est le texte inclus dans le code QR. Et l'absence d'accents est la faut du gvt.
Dernière modification par beuguissime (Le 02/11/2020, à 17:16)
Hors ligne
#20 Le 02/11/2020, à 17:13
- Compte supprimé
Re : (Résolu) Aide pour modifier une ligne de script python
Et l'absence d'accents est la faut du gvt.
Oui, j'ai lu ses explications.
Merci pour toutes ces informations et ton aide.
#21 Le 02/11/2020, à 17:15
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
De rien.
Et donc, as-tu les modifs du message n°16 pour le nommage du fichier PDF ?
Hors ligne
#22 Le 02/11/2020, à 17:41
- Compte supprimé
Re : (Résolu) Aide pour modifier une ligne de script python
Pour le message N°16, ça ira, je le ferai demain. Je me risquerai aussi à modifier les lignes du N°19, mais je vois venir un problème de format de date et heure.
#23 Le 02/11/2020, à 18:12
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
Ah ok, je crois que j'ai enfin compris. Désolé, j'ai le cerveau au ralenti cette après-midi. Oui, donc le problème est que tu veux générer les attestations à l'avance mais que le programme python utilise le jour et l'heure courante pour remplir les champs “Le : xx/yy/zz à : uu:ww”. C'est ça ? Et c'est embêtant pour un contrôle à l'œil sans lecture du code QR qui lui seul contient le bon jour et la bonne heure de la sortie, c'est ça ?
Alors il faut modifier les lignes 119 et 120. Et en effet, ma proposition pour le nommage du fichier n'est pas fonctionnelle à cause de la variable leave_date qui contient des obliques.
Donc voici un code modifé fonctionnel :
from PyPDF2 import PdfFileWriter, PdfFileReader
import qrcode
import datetime
from PIL import ImageFont
from PIL import ImageDraw
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
import sys
import argparse
# Motifs
# travail-achats-sante-famille-handicap-sport_animaux-convocation-missions-enfants
FONT = "NotoMono-Regular.ttf" #"Arial.ttf"
SMALL_LETTER_FONT = "NotoMono-Regular.ttf" #"arial.ttf"
def load_font(font_size):
try:
image_font = ImageFont.truetype(FONT, font_size)
return image_font
except OSError:
try:
image_font = ImageFont.truetype(SMALL_LETTER_FONT, font_size)
return image_font
except OSError:
sys.exit(f"{FONT} n'est pas installé")
def parse_args():
parser = argparse.ArgumentParser(prog='main.py')
parser.add_argument("--first-name", required=True, type=str)
parser.add_argument("--last-name", required=True, type=str)
parser.add_argument("--birth-date", required=True, type=str, help="DD/MM/YYYY")
parser.add_argument("--birth-city", required=True, type=str)
parser.add_argument("--address", required=True, type=str, help="Address Postcode City")
parser.add_argument("--current-city", required=True, type=str)
parser.add_argument("--leave-date", required=True, type=str, help="DD/MM/YYYY")
parser.add_argument("--leave-hour", required=True, type=str, help="HH:MM")
parser.add_argument("--motifs", required=True, type=str, help="- delimited: travail-achats-sante-famille-handicap-sport_animaux-convocation-missions-enfants")
return parser.parse_args()
def draw_first_page_layout():
img = Image.open("input-page1.png")
return np.array(img)
# Create crosses:
def get_cross():
image = Image.new('RGB', (30, 30), color=(255, 255, 255))
image_draw = ImageDraw.Draw(image)
image_font = load_font(35)
image_draw.text((3, -4), f'x', (0, 0, 0), font=image_font)
return np.array(image)
# travail-achats-sante-famille-handicap-sport_animaux-convocation-missions-enfants
def check_motif_boxes(img_array, motifs):
cross = get_cross()
if "travail" in motifs:
img_array[523:553, 169:199] = cross
if "achats" in motifs:
img_array[617:647, 169:199] = cross
if "sante" in motifs:
img_array[732:762, 169:199] = cross
if "famille" in motifs:
img_array[817:847, 169:199] = cross
if "handicap" in motifs:
img_array[904:934, 169:199] = cross
if "sport_animaux" in motifs:
img_array[982:1012, 169:199] = cross
if "convocation" in motifs:
img_array[1114:1144, 169:199] = cross
if "missions" in motifs:
img_array[1195:1225, 169:199] = cross
if "enfants" in motifs:
img_array[1291:1321, 169:199] = cross
return img_array
# QR CODE
def draw_QR_code(img_array,first_name, last_name, birth_date, birth_city, address, leave_date, leave_hour, motifs):
# Dans le QR code del'attestation officielle, motifs sont séparés par des virgules (suvi d'un espace)
motifs = motifs.replace('-', ', ')
# Pas de diacritiques, est-ce normal ? (alors qu'il peut y en avoir dans les cases à remplir)
# Oui, c'est comme c'est qu'est conçu le QR dans les fichiers sources du repo du gouv
qr_text = f"Cree le: {datetime.datetime.now().strftime('%d/%m/%Y a %H:%M')};\n" \
f" Nom: {last_name};\n" \
f" Prenom: {first_name};\n" \
f" Naissance: {birth_date} a {birth_city};\n" \
f" Adresse: {address};\n" \
f" Sortie: {leave_date} a {leave_hour};\n" \
f" Motifs: {motifs}"
qr = qrcode.make(qr_text, border=0)
qr = qr.resize((200, 200))
qr = np.array(qr).astype(np.uint8) * 255
qr = qr.repeat(3).reshape(qr.shape[0], qr.shape[1], -1)
return qr
# Fill args
def fill_save_first_page(img_array, qr, first_name, last_name, birth_date, birth_city, current_city, address, leave_date, leave_hour):
# Draw QR code
img_array[1344:1544, 910:1110] = np.array(qr)
img = Image.fromarray(img_array)
draw = ImageDraw.Draw(img)
font = load_font(22)
font_small = load_font(14)
draw.text((250, 282), f'{first_name} {last_name}', (0, 0, 0), font=font)
draw.text((250, 328), f'{birth_date}', (0, 0, 0), font=font)
draw.text((630, 328), f"{birth_city}", (0, 0, 0), font=font)
draw.text((280, 374), f"{address}", (0, 0, 0), font=font)
draw.text((228, 1368), f"{current_city}", (0, 0, 0), font=font)
# draw.text((205, 1416), datetime.datetime.now().strftime("%d/%m/%Y"), (0, 0, 0), font=font)
# draw.text((535, 1416), datetime.datetime.now().strftime("%H:%M"), (0, 0, 0), font=font)
draw.text((205, 1416), leave_date, (0, 0, 0), font=font)
draw.text((535, 1416), leave_hour, (0, 0, 0), font=font)
# No more in reconfinement
# draw.text((948, 1443), datetime.datetime.now().strftime("%d/%m/%Y à %H:%M"), (0, 0, 0), font=font_small)
plt.imsave("output-1.pdf", np.array(img), format="pdf")
# ---------------------------
# Second Page (Big QR code)
# ---------------------------
def draw_save_second_page(qr):
img = np.array(Image.open('input-page2.png'))
img[:] = 255
qr = Image.fromarray(qr)
qr = qr.resize((qr.size[0] * 3, qr.size[1] * 3))
qr = np.array(qr)
img[113:113 + qr.shape[0], 113:113 + qr.shape[1]] = qr
plt.imsave("output-2.pdf", img, format="pdf")
# --------------------
# Merge PDFs
# --------------------
def merge_pdfs(first_name, last_name, leave_date):
pdf1 = PdfFileReader('output-1.pdf')
pdf2 = PdfFileReader('output-2.pdf')
writer = PdfFileWriter()
writer.addMetadata({
'/Title':'COVID-19 - Déclaration de déplacement',
'/Subject':'Attestation de déplacement dérogatoire',
#'/Keywords': 'covid19','covid-19','attestation','déclaration','déplacement','officielle','gouvernement',
'/Keywords': 'covid19 covid-19 attestation déclaration déplacement officielle gouvernement',
'/Producer':'DNUM/SDIT',
'/Creator':'',
'/Author':'Ministère de l\'intérieur'
})
writer.addPage(pdf1.getPage(0))
writer.addPage(pdf2.getPage(0))
modified_leave_date = "".join(leave_date.split('/')[::-1])
outname = f"Attestation-{last_name}-{first_name}-{modified_leave_date}.pdf"
writer.write(open(outname, "wb"))
print(f"L'attestation a été sauvegardée dans {outname}")
def generate_pdf(first_name, last_name, birth_date, birth_city, current_city, address, leave_date, leave_hour, motifs):
first_page_array = draw_first_page_layout()
first_page_array = check_motif_boxes(first_page_array,motifs)
qr = draw_QR_code(first_page_array, first_name, last_name, birth_date, birth_city, address, leave_date, leave_hour, motifs)
fill_save_first_page(first_page_array, qr, first_name, last_name, birth_date, birth_city,current_city, address, leave_date, leave_hour)
draw_save_second_page(qr)
merge_pdfs(first_name, last_name, leave_date)
print("Le fichier output.pdf a été créé avec succès.")
if __name__ == '__main__':
args = parse_args()
generate_pdf(args.first_name, args.last_name, args.birth_date, args.birth_city, args.current_city, args.address, args.leave_date, args.leave_hour, args.motifs)
def fake_generation():
motifs = ['travail', 'achats', 'sante', 'famille', 'handicap', 'sport_animaux', 'convocation', 'missions', 'enfants']
first_name = "AAAAAAA"
last_name = "BBBBBBBB"
birth_date = "11/20/2000"
birth_city = "BIRTHCITYYYYYYYYYYYYYYYY"
current_city = "CURRENTCITYYYYYYYYYYY"
address = "1112 PLACE DE LARUE QUI EST LONGUE 12312 LONGUEVIIIIIIIIILLE"
leave_date = "11/11/1111"
leave_hour = "12h12"
generate_pdf(first_name, last_name, birth_date, birth_city, current_city, address, leave_date, leave_hour, motifs)
J'ai remplacé Arial.ttf par NotoMono-Regular.ttf.
Voilà un exemple ici de ce qu'on obtient avec cette commande :
$ date; python3 generate_pdf.py --first-name Emmanuel --last-name Macron --birth-date 01/01/1975 --birth-city Houte-Si-Plou --address "Palais de l'Élysée" --current-city Paris --leave-date 02/11/2020 --leave-hour 12:00 --motifs travail
lun. 02 nov. 2020 17:58:57 CET
L'attestation a été sauvegardée dans Attestation-Macron-Emmanuel-20201102.pdf
Le fichier output.pdf a été créé avec succès.
Tu vois grâce au 'date' que j'ai lancé la commande à 17h58 mais que l'heure inscrite est bien 12h00.
Avec un diff sur mon code et le code original tu pourras identifier facilement les changements.
Hors ligne
#24 Le 02/11/2020, à 19:00
- Compte supprimé
Re : (Résolu) Aide pour modifier une ligne de script python
C'est magnifique ! Trop beau
Le pdf et le qr code sont parfaits. En plus, avec tes explications et ce que j'ai lu, je commence un peu à comprendre du fonctionnement de python, j'ai pu ajouter l'heure de sortie dans le nom du fichier.
Encore merci.
Edit : je suis revenu à Arial car je ne trouve pas ta police.
Dernière modification par Compte supprimé (Le 02/11/2020, à 19:15)
#25 Le 02/11/2020, à 19:29
- beuguissime
Re : (Résolu) Aide pour modifier une ligne de script python
Super.
Je n'avais pas Arial sur ma Xubuntu, d'où le changement pour Noto (je croyais sûrement à tort que cette police est dispo sur toutes les variantes d'ubuntu).
Tu as vérifié le code QR en le redécodant manuellement ? Donc pour mon exemple il dit “Créé le 02/11/2020 à 17h58" et indique bien comme date et heure de sortie le 02/11/2020 à 12h00 (j'ai eu la flemme de redécoder le code QR) ?
Tant mieux si cet exemple te permet de mieux appréhender python.
Hors ligne