Outils pour utilisateurs

Outils du site


addpdf_pypdf

Additionner un très grand nombre de fichiers pdf avec PyPdf

Problématique

Un de mes programmes fabrique plusieurs centaines de courriers sous forme de fichiers pdf, et je veux créer un fichier pdf qui regroupe tous ces courriers. Pourquoi? En particulier pour pouvoir les imprimer (mailing papier): si j'ai 1000 courriers à imprimer pour un mailing papier, je me vois mal lancer 1000 fois l'impression!!!

Avec le module PyPdf, c'est assez facile de faire des regroupements de fichiers pdf (http://pybrary.net/pyPdf/). Mais, car il y a un mais, pypdf impose que tous les fichiers à regrouper soient ouverts en même temps, et le système d'exploitation limite le nombre de fichiers ouverts en même temps (pour Windows, c'est environ 500).

Pour dépasser cette limite, j'ai donc développé le code ci-dessous!

Code proposé

Voilà le code proposé:

# Python 2.7
 
import sys, os
 
from pyPdf import PdfFileWriter, PdfFileReader
 
#############################################################################
def _addpdf(listepdf, pdfresult):
    """fonction utilitaire: voir addpdf"""
    pdftous = PdfFileWriter()
    ft = []
    for nf in listepdf:
        ft.append(open(nf, "rb"))
        pdf = PdfFileReader(ft[-1])
        for i in xrange(0, pdf.getNumPages()):
            pdftous.addPage(pdf.getPage(i))
    f = open(pdfresult, "wb")
    pdftous.write(f)
    f.close()
    # fermeture de tous les fichiers "ft" ouverts
    for k in xrange(0, len(ft)):
        ft[k].close()
 
#============================================================================
def addpdf(listepdf, pdfresult, temprep=None, imax=100):
    """fabrique le fichier pdf pdfresult = addition des fichiers pdf de listepdf
       listepdf = liste des noms de fichiers pdf à regrouper
       pdfresult = nom du fichier résultat à créer
       temprep = répertoire des fichiers temporaires
          si = None: fichiers temporaires dans le 'home' de l'utilisateur
       imax = nb maxi de fichiers ouverts en même temps
    """
 
    if len(listepdf)<=imax:
        # on ne dépasse pas le nb de fichiers maxi ouverts: on y va directement
        _addpdf(listepdf, pdfresult)
    else:
        # il faut s'y reprendre à plusieurs fois pour éviter d'avoir
        # trop de fichiers ouverts en même temps!
 
        # répertoire des fichiers temporaires
        if temprep==None:
            temprep = os.path.expanduser("~") # temprep dans le home utilisateur
 
        # init. de la liste des fichiers temporaires
        temp = [] 
 
        i1 = 0
        while True:
            i2 = min(i1+imax, len(listepdf))
            if i2<=i1:
                break
 
            # création d'un fichier temporaire supplémentaire
            temp.append(os.path.join(temprep, "temp%d.pdf" % len(temp)))
 
            _addpdf(listepdf[i1:i2], temp[-1])
 
            i1 = i2
 
        # addition de tous les fichiers temporaires ensemble
        _addpdf(temp, pdfresult)
 
        # destruction des fichiers temporaires
        for nf in temp:
            os.remove(nf) 

Le principe est simple: si on dépasse le nombre maxi de fichiers ouverts en même temps (ici fixé à 100), on segmente la liste en autant de listes de 100 fichiers, et on crée des fichiers temporaires de regroupement. A la fin, il suffit de regrouper les fichiers temporaires en un seul fichier, et c'est fini! Pour faire propre, on détruit les fichiers temporaires.

Exemple d'utilisation

import glob
listefic = glob.glob(os.path.join("auteurs", "*.pdf"))
listefic.sort()
addpdf(listefic, "pdftous.pdf", ".")

Ici, on a tous les fichiers pdf à regrouper dans le sous-répertoire 'auteurs'.

Chacun de ces fichiers peut avoir un nombre quelconque de pages: elles seront toutes ajoutées dans le bon ordre.

On peut trier cette liste: cela déterminera dans quel ordre ces fichiers se placeront dans le pdf résultat.

Et on appelle la fonction de regroupement addpdf, en donnant comme répertoire temporaire le répertoire courant. Si on ne donne pas un répertoire temporaire, les fichiers temporaires seront placés dans le 'home' de l'utilisateur.

Le pdf résultat sera “pdftous.pdf”.

Les performances sont satisfaisantes: on regroupe 1000 courriers pdf d'une page en un seul pdf en une minute environ.


Amusez-vous bien!

addpdf_pypdf.txt · Dernière modification: 2011/12/24 08:45 par tyrtamos

Outils de la page