Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#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 tongue
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 smile

#10 Le 01/11/2020, à 14:12

beuguissime

Re : (Résolu) Aide pour modifier une ligne de script python

Super si ça marche ! wink
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 ? big_smile

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 tongue

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 tongue

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 ! wink)    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 smile

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. wink

Hors ligne