"Création d'un service qui modifie l'historique d'utilisation de Suica mobile afin qu'il puisse être facilement utilisé pour le règlement des dépenses" Transformez le fichier PDF de l'historique d'utilisation de Suica mobile au format pandas DataFrame avec tabula-py Cliquez ici pour le produit fini https://www.mobilesuica.work
La gestion des erreurs est un seuil élevé pour les amateurs comme l'auteur. C'est difficile car il est fait en prévision des exceptions qui peuvent survenir et du fonctionnement erroné de l'utilisateur (bien qu'il soit ajouté dans les résultats des tests, bien sûr).
Les deux traitements d'erreurs suivants sont considérés cette fois.
En regardant les liens ci-dessous et d'autres pages, j'ai pensé qu'il serait correct d'attraper l'exception avec try-except et de l'augmenter avec augmenter. La plupart des choses que vous récupérez sur GitHub sont comme ça. * Comment implémenter la notification d'erreur dans le programme Python
J'en ai trouvé un pratique appelé ** PyPDF2 **.
test.py
import PyPDF2
with open('a.pdf','rb') as f:
pageNum = PyPDF2.PdfFileReader(f).getNumPages()
print(f"Le nombre de pages{pageNum}est")
Résultat d'exécution
(app-root) bash-4.2# python3 test.py
Le nombre de pages est de 2
Si vous transmettez un fichier non PDF, il ressemblera à ceci
test.py
fileList = ['a.pdf','test.py']
for fileName in fileList:
with open(fileName,'rb') as f:
pageNum = PyPDF2.PdfFileReader(f).getNumPages()
print(f"{fileName}Le nombre de pages est{pageNum}est")
Résultat d'exécution
(app-root) bash-4.2# python3 test.py
a.Le nombre de pages en pdf est de 2
Traceback (most recent call last):
File "test.py", line 9, in <module>
pageNum = PyPDF2.PdfFileReader(f).getNumPages()
File "/opt/app-root/lib/python3.6/site-packages/PyPDF2/pdf.py", line 1084, in __init__
self.read(stream)
File "/opt/app-root/lib/python3.6/site-packages/PyPDF2/pdf.py", line 1696, in read
raise utils.PdfReadError("EOF marker not found")
PyPDF2.utils.PdfReadError: EOF marker not found
** PyPDF2.utils.PdfReadError: marqueur EOF introuvable ** semble être une exception que PyPDF2 lance lorsqu'il ne s'agit pas d'un fichier PDF. Le message semble changer en fonction du fichier passé, et il y avait également ** Impossible de lire le fichier PDF malformé **. Dans tous les cas, si vous ne gérez pas bien cette exception, le programme s'arrêtera ici.
Pour le moment, ce serait bien de pouvoir récupérer ** PyPDF2.utils.PdfReadError **.
test.py
try:
fileList = ['a.pdf','test.py']
for fileName in fileList:
with open(fileName,'rb') as f:
pageNum = PyPDF2.PdfFileReader(f).getNumPages()
print(f"{fileName}Le nombre de pages est{pageNum}est")
except PyPDF2.utils.PdfReadError as e:
print(f"ERROR: {e}Le PDF est incorrect")
Résultat d'exécution
(app-root) bash-4.2# python3 test.py
a.Le nombre de pages en pdf est de 2
ERROR:Marqueur EOF introuvable Le PDF est incorrect
Désormais, même si une exception se produit, le traitement peut être poursuivi. En fin de compte, vous pouvez informer l'utilisateur qui a téléchargé le fichier non PDF.
Cependant, il y a un inconvénient en soi. Puisqu'il n'y a pas de traceback, vous ne saurez pas plus tard où le programme s'est arrêté dans le code source. La solution est simple, il suffit d'utiliser un module appelé ** traceback **.
test.py
import traceback
#...réduction
except PyPDF2.utils.PdfReadError as e:
print(f"ERROR: {e}Le PDF est incorrect")
traceback.print_exc()
Résultat d'exécution
(app-root) bash-4.2# python3 test.py
a.Le nombre de pages en pdf est de 2
ERROR:Marqueur EOF introuvable Le PDF est incorrect
Traceback (most recent call last):
File "test.py", line 10, in <module>
pageNum = PyPDF2.PdfFileReader(f).getNumPages()
File "/opt/app-root/lib/python3.6/site-packages/PyPDF2/pdf.py", line 1084, in __init__
self.read(stream)
File "/opt/app-root/lib/python3.6/site-packages/PyPDF2/pdf.py", line 1696, in read
raise utils.PdfReadError("EOF marker not found")
PyPDF2.utils.PdfReadError: EOF marker not found
Vous pouvez voir que la traceback est sortie contrairement au précédent.
En regardant le code source des autres, il dit ** sauf Exception comme e: **, donc je ramasse toutes les exceptions. Cela semble être appelé la classe de base. Après avoir lu diverses choses, si vous souhaitez modifier le traitement en fonction de l'exception que vous avez sélectionnée, spécifiez quelle exception comme ** PyPDF2.utils.PdfReadError **, sinon si le traitement est le même ** sauf Exception comme e: * * Mais ça a l'air bien. Par exemple, est-ce que c'est comme ça?
test.py
try:
fileList = ['test.py']
for fileName in fileList:
with open(fileName,'rb') as f:
pageNum = PyPDF2.PdfFileReader(f).getNumPages()
print(f"{fileName}Le nombre de pages est{pageNum}est")
df = tabula.read_pdf(fileName,pages='all',pandas_options={'dtype':'object'})
except PyPDF2.utils.PdfReadError as e:
print(f"ERROR: {e}Le PDF est incorrect")
except Exception as e:
print(f"ERROR: {e}Quelque chose ne va pas")
À propos, si vous écrivez la classe de base en premier, elle entrera la route de traitement là-bas, alors essayez d'écrire la classe de base en dernier.
Il n'y a pas d'exceptions à donner un PDF non tabulaire, donc tout ce que vous avez à faire est de vous assurer qu'il ne s'agit pas d'un PDF Suica mobile. Tout d'abord, lisez l'en-tête DataFrame. J'ai préparé un fichier vierge (blank.pdf) en tant que mauvais PDF.
test.py
fileList = ['a.pdf','blank.pdf']
for fileName in fileList:
df = tabula.read_pdf(fileName,pages='all',pandas_options={'dtype':'object'})
h = df[0].columns.values.tolist()
print(f"L'en-tête est{h}est")
Résultat d'exécution
(app-root) bash-4.2# python3 test.py
L'en-tête est['Mois', 'journée', 'Type', 'Station utilisée', 'Type.1', 'Station utilisée.1', 'Équilibre', 'différence']est
Traceback (most recent call last):
File "test.py", line 11, in <module>
h = df[0].columns.values.tolist()
IndexError: list index out of range
Apparemment, cela donne une erreur d'index, c'est donc une exception. Pour gérer les erreurs supplémentaires, il est possible que l'en-tête DataFrame ait été supprimé, mais un PDF tabulaire différent du PDF Mobile Suica a été téléchargé. Si vous vérifiez le contenu de l'en-tête, il apparaîtra, mais il semble créer un bogue différent, alors arrêtez la gestion des erreurs jusqu'à ce point. Le programme qui reçoit finalement la liste des fichiers téléchargés par l'utilisateur en tant que fileList et la traite est comme ça.
test.py
import tabula
import PyPDF2
import traceback
import pandas as pd
try:
fileList = ['a.pdf','blank.pdf']
dfList = []
for fileName in fileList:
with open(fileName,'rb') as f:
pageNum = PyPDF2.PdfFileReader(f).getNumPages()
df = tabula.read_pdf(fileName,pages='all',pandas_options={'dtype':'object'})
if df[0].columns.values.tolist():
for i in range(len(df)):
dfList.append(df[i])
print(f"{fileName}Peut être traité correctement")
d = pd.concat(dfList,ignore_index=True)
except PyPDF2.utils.PdfReadError as e:
print(f"ERROR: {e} {fileName}Ne semble pas être en PDF")
traceback.print_exc()
except IndexError as e:
print(f"ERROR: {e} {fileName}Est un PDF, mais il ne semble pas être un PDF mobile Suica")
traceback.print_exc()
except Exception as e:
print(f"ERROR: {e} {fileName}Quelque chose ne va pas")
traceback.print_exc()
Résultat d'exécution
(app-root) bash-4.2# python3 test.py
a.pdf a été traité correctement
ERROR: list index out of range blank.pdf est un PDF, mais il semble que ce ne soit pas un PDF mobile Suica
Traceback (most recent call last):
File "test.py", line 13, in <module>
if df[0].columns.values.tolist():
IndexError: list index out of range
Comme le traitement jusqu'à ce point sera appelé en tant que fonction, le message d'erreur n'apparaîtra que dans le journal du serveur et ne sera pas visible par l'utilisateur. Ce message d'erreur doit être renvoyé à l'appelant pour être visible par l'utilisateur. Si vous le renvoyez tel quel avec ** rise **, seul le message d'erreur d'origine sera envoyé. Quand il est transformé en fonction, il ressemble à ceci
test.py
def test():
try:
fileList = ['copy.sh']
dfList = []
for fileName in fileList:
with open(fileName,'rb') as f:
pageNum = PyPDF2.PdfFileReader(f).getNumPages()
df = tabula.read_pdf(fileName,pages='all',pandas_options={'dtype':'object'})
if df[0].columns.values.tolist():
for i in range(len(df)):
dfList.append(df[i])
print(f"{fileName}Peut être traité correctement")
d = pd.concat(dfList,ignore_index=True)
print(d)
except PyPDF2.utils.PdfReadError as e:
print(f"ERROR: {e} {fileName}Ne semble pas être en test PDF()dans")
raise
except IndexError as e:
print(f"ERROR: {e} {fileName}Est un PDF, mais il ne semble pas être un PDF mobile Suica")
except Exception as e:
print(f"ERROR: {e} {fileName}Quelque chose ne va pas")
try:
test()
except Exception as e:
print(f"{e}Votre interlocuteur")
Résultat d'exécution
(app-root) bash-4.2# python3 test.py
ERROR: Could not read malformed PDF file copy.sh ne semble pas être en test PDF()dans
Impossible de lire l'appelant du fichier PDF malformé
Je ne sais pas quel fichier était mauvais. La seule façon de résoudre ce problème était de faire une exception, ce qui était un peu bosselé, mais j'étais soulagé que cela se soit avéré assez facile. Il y a une explication facile à comprendre sur ce site. Ajoutez simplement deux lignes! !! * Exemple de code (3 types) pour créer et utiliser des exceptions en Python
Voici donc celui avec votre propre gestion des exceptions
test.py
import tabula
import PyPDF2
import traceback
import pandas as pd
class ConvertError(Exception):
pass
def test():
try:
fileList = ['copy.sh']
dfList = []
for fileName in fileList:
with open(fileName,'rb') as f:
pageNum = PyPDF2.PdfFileReader(f).getNumPages()
df = tabula.read_pdf(fileName,pages='all',pandas_options={'dtype':'object'})
if df[0].columns.values.tolist():
for i in range(len(df)):
dfList.append(df[i])
print(f"{fileName}Peut être traité correctement")
d = pd.concat(dfList,ignore_index=True)
print(d)
except PyPDF2.utils.PdfReadError as e:
traceback.print_exc()
errorText = f"ERROR: {e} {fileName}Ne semble pas être en PDF=> test()dans"
print(errorText)
raise ConvertError(errorText)
except IndexError as e:
traceback.print_exc()
errorText = f"ERROR: {e} {fileName}Est un PDF, mais il ne semble pas être un PDF mobile Suica"
print(errorText)
raise ConvertError(errorText)
except Exception as e:
traceback.print_exc()
errorText = f"ERROR: {e} {fileName}Quelque chose ne va pas"
print(errorText)
raise ConvertError(errorText)
try:
test()
except Exception as e:
print(f"{e}Votre interlocuteur")
Résultat d'exécution
(app-root) bash-4.2# python3 test.py
Traceback (most recent call last):
File "test.py", line 15, in test
pageNum = PyPDF2.PdfFileReader(f).getNumPages()
File "/opt/app-root/lib/python3.6/site-packages/PyPDF2/pdf.py", line 1084, in __init__
self.read(stream)
File "/opt/app-root/lib/python3.6/site-packages/PyPDF2/pdf.py", line 1697, in read
line = self.readNextEndLine(stream)
File "/opt/app-root/lib/python3.6/site-packages/PyPDF2/pdf.py", line 1937, in readNextEndLine
raise utils.PdfReadError("Could not read malformed PDF file")
PyPDF2.utils.PdfReadError: Could not read malformed PDF file
ERROR: Could not read malformed PDF file copy.sh ne semble pas être PDF=> test()dans
ERROR: Could not read malformed PDF file copy.sh ne semble pas être PDF=> test()Dans l'appelant
Recommended Posts