6
votes

La paranoïa, la journalisation excessive et la manipulation des exceptions sur des scripts simples traitant des fichiers. Est-ce normal?

Je me trouve en utilisant Python pour beaucoup de scripts de gestion de fichiers comme celui ci-dessous. Tout en recherchant des exemples sur le net, je suis surpris de savoir comment peu de journalisation et de manutention des exceptions figurent sur les exemples. Chaque fois que j'écris un nouveau script, mon intention n'est pas de se retrouver comme celle ci-dessous, mais si elle traite des fichiers, peu importe ce que ma paranoïa prend la relève et que le résultat final n'est rien comme les exemples que je vois sur le net. Comme je suis un débutant, je voudrais savoir si c'est normal ou non. Sinon, comment traitez-vous avec les inconnus et les craintes de supprimer des informations précieuses? xxx


2 commentaires

Il h. Eh bien, il n'y a rien faux avec ce niveau de journalisation / paranoïa, je partage un bit pour les scripts de modification de fichier.


Je n'ai pas de réponse convaincante, mais notez que la majeure partie du code supplémentaire ici est due à (a) des systèmes de fichiers ne prises en charge pas de grandes transactions, et (b) manque de syntaxe concise dans Python pour ajouter des informations supplémentaires lisibles par l'homme à toutes les exceptions. cela pourrait être jeté.


5 Réponses :


1
votes

Cela me semble raisonnable. Cela dépend de la manière dont vos données sont importantes.

Je commence souvent comme ça et que la journalisation soit facultative, avec un drapeau défini en haut du fichier (ou par l'appelant) définissant la journalisation ou la désactivation. Vous pouvez également avoir une verbosité.

Généralement, après que quelque chose fonctionne depuis un certain temps et que je n'arrête plus de lire les journaux et de construire des fichiers journaux géants que je ne lis jamais. Cependant, si quelque chose va mal, il est bon de savoir qu'ils sont là.


1 commentaires

Ce dernier paragraphe me arrive aussi beaucoup!



3
votes

C'est bon d'être un peu paranoïaque. Mais il y a différents types de paranoïa :). Au cours de la phase de développement, j'utilise beaucoup de déclarations de débogage afin que je puisse voir où je vais mal (si je me trompe). Parfois, je laisserai ces déclarations dans, mais utilisez un drapeau pour contrôler si elles doivent être affichées ou non (à peu près un drapeau de débogage). Vous pouvez également avoir un drapeau "verbosité" pour contrôler la quantité de journalisation que vous faites.

L'autre type de paranoïa est livré avec des contrôles de santé intellectuelle. Cette paranoïa entre en jeu lorsque vous vous appuyez sur des données ou des outils externes - à peu près tout ce qui ne sort pas de votre programme. Dans ce cas, il ne fait jamais de mal d'être paranoïaque (surtout avec des données que vous recevez - ne faites jamais confiance ).

Il est également correct d'être paranoïaque si vous vérifiez pour voir si une opération particulière s'est terminée avec succès. Cela ne fait qu'une partie de la manipulation normale des erreurs. Je remarque que vous effectuez des fonctions telles que la suppression des répertoires et des fichiers. Ce sont des opérations pouvant éventuellement échouer, et vous devez donc traiter avec le scénario où ils échouent. Si vous l'ignorez simplement, votre code pourrait se retrouver dans un état indéterminé / indéfini et pourrait potentiellement faire de mauvaises choses (ou au moins indésirables).

En ce qui concerne les fichiers journaux et les fichiers de débogage, vous pouvez les laisser dans si vous le souhaitez. J'effectue habituellement une quantité décente de journalisation; Juste assez pour me dire ce qui se passe. Bien sûr, cela est subjectif. La clé est de vous assurer que vous ne vous noyez pas dans la journalisation; où il y a tellement d'informations que vous ne pouvez pas le choisir facilement. L'enregistrement général vous aide à déterminer le moment où un script que vous avez écrit cesse de travailler soudainement. Au lieu de passer à travers le programme pour le comprendre, vous pouvez obtenir une idée approximative de l'endroit où le problème passe par vos journaux.


1 commentaires

Utilisation d'un debug_level global = 0B001 ou si de nombreux niveaux dont vous avez besoin est un excellent moyen de le faire. Ensuite, vous venez d'avoir un débogage (message, niveau): Si le niveau est un excellent moyen de le faire. Alors au lieu de imprimer myTestval vous pouvez taper débogg (myTestval, 0b010) - Bien sûr, vous pouvez également définir des constantes telles que test , etc. Début de votre dossier ... et bien sûr, vous pouvez également masquer au lieu de faire des comparaisons ...



8
votes

Apprendre à laisser aller (ou comment j'ai appris à vivre avec la bombe) ...

Demandez-vous ceci: Qu'avez-vous vraiment peur, et comment allez-vous le gérer si cela se produit? Dans l'exemple que vous fournissez, vous souhaitez éviter la perte de données. La façon dont vous avez gérée est de rechercher chaque combinaison de conditions que vous pensez être une erreur et de placer d'énormes quantités de journalisation. Les choses vont toujours se tromper et il n'est pas clair que le fait d'avoir une grande quantité de journalisation sera un bon moyen de le gérer. Esquisser ce que vous essayez d'atteindre: xxx

donc quel genre de choses pourraient se tromper dans ce processus? Eh bien, il existe de nombreuses façons dans lesquelles les opérations de fichier de déplacement pourraient à la barf due au système de fichiers sous-jacent. Pouvons-nous tous les énumérer et fournir de belles façons de les traiter? Non ... Mais en général, vous allez traiter avec eux de la même manière. Parfois, une erreur n'est qu'une erreur n'est qu'une erreur quel que soit ce que c'est.

Donc, dans ce cas, si une erreur survient, vous souhaitez abandonner et annuler les modifications. La façon dont vous avez décidé de le faire est de créer une copie de sauvegarde et de le restaurer lorsque quelque chose ne va pas. Mais votre erreur la plus probable est la totalité du système de fichiers auquel cas ces étapes sont susceptibles d'échouer .... OK, il s'agit donc d'un problème assez courant - si vous êtes inquiet des erreurs inconnues à tout moment, comment arrêtez-vous votre La trajectoire de restauration d'aller mal?

La réponse générale est assurée d'abord que vous faites d'abord un travail intermédiaire, puis prenez une étape gênante (espérons-le atomique). Dans votre cas, vous devez retourner votre rétablissement. Au lieu de construire une copie comme sauvegarde, créez une copie du résultat. Si tout réussit, vous pouvez ensuite échanger le nouveau résultat pour l'ancien arbre d'origine. Ou, si vous êtes vraiment paranoïaque, vous pouvez laisser cette étape pour un humain. L'avantage ici est que si quelque chose ne va pas, vous pouvez simplement abandonner et jeter l'état partiel que vous avez construit.

Votre structure devient alors: xxx

D'ailleurs, vous avez un bogue dans votre script actuel que ce code PSEDEDO est plus évident: si vous avez des fichiers avec des noms identiques dans différentes branches, ils vont écraser mutuellement dans la nouvelle version aplatie.

Le deuxième point sur ce code PSEDEO est que toute la manipulation des erreurs est au même endroit (c.-à-d. Envelopper le nouveau répertoire et la copie récursive à l'intérieur d'un seul bloc d'essai et attraper toutes les erreurs après cela), cela résout votre problème d'origine sur le Grand rapport de journalisation / vérification des erreurs au code de travail réel. xxx


1 commentaires

En y réfléchissant, c'est clairement la manière la plus logique. Comme toutes les erreurs sont traitées avec la restauration totale de l'état précédent, votre solution a vraiment le plus de sens pour regrouper toutes les étapes susceptibles de provoquer une erreur dans un seul mécanisme de capture. Il est encore plus facile d'implémenter une vérification de la CRC sur les fichiers de la paranoïa supplémentaire avant de supprimer les données d'origine !. Sur mon code, j'utilisais Shuttil.Move qui soulève une exception sur les fichiers avec des noms égaux, donc aucun écrasement n'est survenu. Ici, un chèque pour les noms de fichiers égaux doit être effectué mais il est vraiment trivial.



2
votes

La paranoïa peut définitivement obscurcir ce que votre code tente de faire. C'est une très mauvaise chose, pour plusieurs raisons. Il cache des bugs. Il rend le programme plus difficile à modifier lorsque vous en avez besoin pour faire autre chose. Cela rend plus difficile de déboguer.

Assumer que Amoss ne peut pas vous guérir de votre paranoïa, voici comment je pourrais réécrire le programme. Notez que:

  • Chaque bloc de code contenant beaucoup de paranoïa est divisé dans sa propre fonction.

  • Chaque fois qu'une exception est capturée, il est re-élevé , jusqu'à ce qu'il soit enfin pris dans la fonction ". Cela élimine le besoin de variables comme restaore_backup et restaore_fail .

  • Le coeur du programme (en Flatten_dir ) Il suffit de 17 lignes longues et sans paranoïa.


    xxx

1 commentaires

La solution d'Amoss semble plus appropriée mais utilisant des fonctions comme moyen de nettoyer le mécanisme de code de base de toutes les exceptions et de la journalisation est une technique utile que je mettrai la mise en œuvre de mon code à partir de maintenant.



0
votes

s'il est correct de quitter le travail à moitié fait fort> sur erreur (seulement certains fichiers déplacés), tant qu'aucun fichier n'est perdu, le répertoire de sauvegarde est inutile. Vous pouvez donc écrire un code de manière spectaculaire:

import os, logging

def flatten_dir(dirname):
    for root, dirs, files in os.walk(dirname, topdown=False):
        assert len(dirs) == 0
        if root != dirname:
            for file in files:
                full_filename = os.path.join(root, file)
                target_filename = os.path.join(dirname, file)
                if os.path.exists(target_filename):
                    raise Exception('Unable to move file "%s" because "%s" already exists'
                                    % (full_filename, target_filename))
                os.rename(full_filename, target_filename)
            os.rmdir(root)

def main():
    try:
        flatten_dir(somedir)
    except:
        logging.exception('Failed to flatten directory "%s".' % somedir)
        print "ERROR: Failed to flatten directory. Check log files for details."


0 commentaires