Maison  >  Article  >  développement back-end  >  Outils de débogage Python couramment utilisés

Outils de débogage Python couramment utilisés

巴扎黑
巴扎黑original
2017-04-30 15:52:281753parcourir

Ce qui suit est un aperçu des outils que j'utilise lors du débogage ou de l'analyse. Si vous connaissez un meilleur outil, veuillez le laisser dans les commentaires sans donner une introduction complète.

Journal

C'est vrai, c'est un journal. L'importance de conserver des journaux adéquats dans votre application ne peut être surestimée. Vous devriez enregistrer les éléments importants. Si vos journaux sont suffisamment bons, vous pouvez trouver le problème simplement en consultant les journaux. Cela vous fait gagner beaucoup de temps.

Si vous avez utilisé des instructions print de manière aléatoire dans votre code, arrêtez maintenant. Utilisez plutôt logging.debug. Vous pourrez continuer à les réutiliser à l’avenir, ou tous les désactiver, etc.

Suivi

Parfois, une meilleure approche consiste à examiner quelles instructions ont été exécutées. Vous pouvez utiliser le débogueur de certains IDE pour parcourir les étapes, mais vous devez savoir exactement quelles instructions vous recherchez, sinon l'ensemble du processus se déroulera très lentement.
Le module de trace de la bibliothèque standard peut imprimer toutes les instructions exécutées dans les modules qu'il contient pendant l'exécution. (Comme faire un rapport de projet)

python -mtrace –trace script.py

Cela produira beaucoup de résultats (chaque ligne exécutée sera imprimée, vous souhaiterez peut-être grep pour filtrer les modules qui vous intéressent
). Par exemple :

python -mtrace –trace script.py | egrep '^(mod1.py|mod2.py)'

Débogueur

Ce qui suit est une introduction de base que tout le monde devrait désormais connaître :

import pdb
pdb.set_trace() # 开启pdb提示

Ou

try:
(一段抛出异常的代码)
except:
    import pdb
    pdb.pm() # 或者 pdb.post_mortem()

Ou (entrez c pour lancer l'exécution du script)

python -mpdb script.py

Dans l'environnement de boucle entrée-calcul-sortie (Remarque : REPL, abréviation de READ-EVAL-PRINT-LOOP), les opérations suivantes peuvent être effectuées :

  • c ou continuer


  • q ou quitter


  • l ou liste, afficher le code source du cadre d'étape actuel


  • w ou où, retracer le processus d'appel


  • d ou vers le bas, reculer d'une image (note : équivalent au rollback)


  • u ou vers le haut, avancer d'une image


  • (Entrée), répétez la commande précédente

Presque toutes les instructions restantes (à l'exception de quelques autres commandes) sont analysées sous forme de code Python sur l'image d'étape actuelle.

Si ce n'est pas assez difficile pour vous, essayez le smiley : il vous montre les variables et vous pouvez l'utiliser pour suivre le programme à distance.

Un meilleur débogueur

Remplacement immédiat pour pdb :
ipdb (easy_install ipdb) – similaire à ipython (avec saisie semi-automatique, couleurs d'affichage, etc.)
pudb (easy_install pudb) – basé sur des malédictions (similaire à une interface graphique), particulièrement adapté à la navigation dans le code source

​Débogueur à distance

Méthode d'installation :

sudo apt-get install winpdb

Remplacez le pdb.set_trace() précédent par la méthode suivante :

import rpdb2
rpdb2.start_embedded_debugger("secretpassword")

Maintenant, lancez winpdb, association de fichiers

Vous n'aimez pas Winpdb ? Vous pouvez également envelopper directement PDB pour qu'il s'exécute sur TCP !

Faites ceci :

import loggging

class Rdb(pdb.Pdb):
    """
    This will run pdb as a ephemeral telnet service. Once you connect no one
    else can connect. On construction this object will block execution till a
    client has connected.

    Based on https://github.com/tamentis/rpdb I think ...

    To use this::

        Rdb(4444).set_trace()

    Then run: telnet 127.0.0.1 4444
    """
    def __init__(self, port=0):
        self.old_stdout = sys.stdout
        self.old_stdin = sys.stdin
        self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.listen_socket.bind(('0.0.0.0', port))
        if not port:
            logging.critical("PDB remote session open on: %s", self.listen_socket.getsockname())
            print >> sys.__stderr__, "PDB remote session open on:", self.listen_socket.getsockname()
            sys.stderr.flush()
        self.listen_socket.listen(1)
        self.connected_socket, address = self.listen_socket.accept()
        self.handle = self.connected_socket.makefile('rw')
        pdb.Pdb.__init__(self, completekey='tab', stdin=self.handle, stdout=self.handle)
        sys.stdout = sys.stdin = self.handle

    def do_continue(self, arg):
        sys.stdout = self.old_stdout
        sys.stdin = self.old_stdin
        self.handle.close()
        self.connected_socket.close()
        self.listen_socket.close()
        self.set_continue()
        return 1

    do_c = do_cont = do_continue

def set_trace():
    """
    Opens a remote PDB on first available port.
    """
    rdb = Rdb()
    rdb.set_trace()

Vous voulez juste un environnement REPL ? Et si vous essayiez IPython ?

Si vous n'avez pas besoin d'un débogueur complet, il vous suffit de démarrer un IPython de la manière suivante :

import IPython
IPython.embed()

Outils Linux standards

Je suis souvent surpris de voir à quel point ils sont sous-utilisés. Vous pouvez utiliser ces outils pour résoudre un large éventail de problèmes : des problèmes de performances (trop d'appels système, allocations de mémoire, etc.) aux blocages, problèmes de réseau, problèmes de disque, etc.
Le plus utile est strace, qui est le plus direct. Il vous suffit d'exécuter la commande sudo strace -p 12345 ou strace -f (-f signifie suivre le processus enfant sortant du fork en même temps), et c'est tout. . La sortie sera généralement assez volumineuse, vous souhaiterez donc peut-être la rediriger vers un fichier pour une analyse plus approfondie (ajoutez simplement &> au nom du fichier).

Ensuite, il y a ltrace, qui est quelque peu similaire à strace. La différence est qu'il génère des appels de fonction de bibliothèque. Les paramètres sont à peu près les mêmes.

Il existe également lsof utilisé pour indiquer la signification des valeurs de handle que vous voyez dans ltrace/strace. Par exemple :

lsof -p 12345

Meilleur suivi

Il est facile à utiliser et peut faire beaucoup de choses - tout le monde devrait installer htop !

sudo apt-get install htop
sudo htop

Recherchez maintenant les processus que vous souhaitez et entrez :

s - 代表系统调用过程(类似strace)
L - 代表库调用过程(类似ltrace)
l - 代表lsof

Surveillance

Il n'y a pas de bonne surveillance continue des serveurs, mais si jamais vous rencontrez quelque chose de bizarre, comme pourquoi tout fonctionne si lentement, que font toutes ces ressources système ? . . Lorsque vous voulez comprendre ces problèmes mais que vous n'avez nulle part où commencer, vous n'êtes pas obligé d'utiliser des outils comme iotop, iftop, htop, iostat, vmstat, utilisez simplement dstat ! Il peut faire la plupart des choses que nous avons mentionnées précédemment, et peut-être même mieux !
Il vous affichera en permanence les données de manière compacte et mise en évidence par le code (différent de iostat, vmstat), et vous pourrez souvent voir les données passées (contrairement à iftop, iostop, htop).

Courez :

dstat --cpu --io --mem --net --load --fs --vm --disk-util --disk-tps --freespace --swap --top-io --top-bio-adv

  很可能有一种更简短的方式来写上面这条命令,

  这是一个相当复杂而又强大的工具,但是这里我只提到了一些基本的内容(安装以及基础的命令)

sudo apt-get install gdb python-dbg
zcat /usr/share/doc/python2.7/gdbinit.gz > ~/.gdbinit

  用python2.7-dbg 运行程序:

sudo gdb -p 12345

  现在使用:

bt - 堆栈跟踪(C 级别)
pystack - python 堆栈跟踪,不幸的是你需要有~/.gdbinit 并且使用python-dbg
c - 继续

  发生段错误?用faulthandler !

  python 3.3版本以后新增的一个很棒的功能,可以向后移植到python2.x版本。只需要运行下面的语句,你就可以大抵知道什么原因引起来段错误。

import faulthandler
faulthandler.enable()

  内存泄露

  嗯,这种情况下有很多的工具可以使用,其中有一些专门针对WSGI的程序比如Dozer,但是我最喜欢的当然是objgraph。使用简单方便,让人惊讶!

  它没有集成WSGI或者其他,所以你需要自己去发现运行代码的方法,像下面这样:

import objgraph
objs = objgraph.by_type("Request")[:15]
objgraph.show_backrefs(objs, max_depth=20, highlight=lambda v: v in objs,
filename="/tmp/graph.png")
Graph written to /tmp/objgraph-zbdM4z.dot (107 nodes)
Image generated as /tmp/graph.png

  你会得到像这样一张图(注意:它非常大)。你也可以得到一张点输出。

  内存使用

  有时你想少用些内存。更少的内存分配常常可以使程序执行的更快,更好,用户希望内存合适好用)
有许多可用的工具,但在我看来最好用的是pytracemalloc。与其他工具相比,它开销非常小(不需要依赖于严重影响速度的sys.settrace)而且输出非常详尽。但安装起来比较痛苦,你需要重新编译python,但有了apt,做起来也非常容易。

  只需要运行这些命令然后去吃顿午餐或者干点别的:

apt-get source python2.7
cd python2.7-*
wget? https://github.com/wyplay/pytracemalloc/raw/master/python2.7_track_free_list.patch
patch -p1 < python2.7_track_free_list.patch
debuild -us -uc
cd ..
sudo dpkg -i python2.7-minimal_2.7*.deb python2.7-dev_*.deb

  接着安装pytracemalloc (注意如果你在一个virtualenv虚拟环境下操作,你需要在重新安装python后再次重建 – 只需要运行 virtualenv myenv)

pip install pytracemalloc

  现在像下面这样在代码里包装你的应用程序

import tracemalloc, time
tracemalloc.enable()
top = tracemalloc.DisplayTop(
    5000, # log the top 5000 locations
    file=open(&#39;/tmp/memory-profile-%s&#39; % time.time(), "w")
)
top.show_lineno = True
try:
    # code that needs to be traced
finally:
    top.display()

  输出会像这样:

2013-05-31 18:05:07: Top 5000 allocations per file and line
 #1: .../site-packages/billiard/_connection.py:198: size=1288 KiB, count=70 (+0),
average=18 KiB
 #2: .../site-packages/billiard/_connection.py:199: size=1288 KiB, count=70 (+0),
average=18 KiB
 #3: .../python2.7/importlib/__init__.py:37: size=459 KiB, count=5958 (+0),
average=78 B
 #4: .../site-packages/amqp/transport.py:232: size=217 KiB, count=6960 (+0),
average=32 B
 #5: .../site-packages/amqp/transport.py:231: size=206 KiB, count=8798 (+0),
average=24 B
 #6: .../site-packages/amqp/serialization.py:210: size=199 KiB, count=822 (+0),
average=248 B
 #7: .../lib/python2.7/socket.py:224: size=179 KiB, count=5947 (+0), average=30
B
 #8: .../celery/utils/term.py:89: size=172 KiB, count=1953 (+0), average=90 B
 #9: .../site-packages/kombu/connection.py:281: size=153 KiB, count=2400 (+0),
average=65 B
 #10: .../site-packages/amqp/serialization.py:462: size=147 KiB, count=4704
(+0), average=32 B

  …

  很美,不是吗?

  补充:更多有关调试的内容见这里。

  原文链接: Ionel Cristian Mărieș   翻译: 伯乐在线 - 高磊

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn