• Stars
    star
    1,574
  • Rank 29,738 (Top 0.6 %)
  • Language
    Python
  • License
    GNU General Publi...
  • Created about 12 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An improbable web debugger through WebSockets

wdb - Web Debugger

Build Status Coverage Status

Description

wdb is a full featured web debugger based on a client-server architecture.

The wdb server which is responsible of managing debugging instances along with browser connections (through websockets) is based on Tornado. The wdb clients allow step by step debugging, in-program python code execution, code edition (based on CodeMirror) setting breakpoints...

Due to this architecture, all of this is fully compatible with multithread and multiprocess programs.

wdb works with python 2 (2.6, 2.7), python 3 (3.2, 3.3, 3.4, 3.5) and pypy. Even better, it is possible to debug a python 2 program with a wdb server running on python 3 and vice-versa or debug a program running on a computer with a debugging server running on another computer inside a web page on a third computer!

Even betterer, it is now possible to pause a currently running python process/thread using code injection from the web interface. (This requires gdb and ptrace enabled)

In other words it's a very enhanced version of pdb directly in your browser with nice features.

Installation:

Global installation:

    $ pip install wdb.server

In virtualenv or with a different python installation:

    $ pip install wdb

(You must have the server installed and running)

Quick test

To try wdb, first you have to start the wdb server:

    $ wdb.server.py &

Optionally, you can automatically activate daemons with systemd (socket activation):

    $ cd /etc/systemd/system
    # curl -O https://raw.githubusercontent.com/Kozea/wdb/master/server/wdb.server.service
    # curl -O https://raw.githubusercontent.com/Kozea/wdb/master/server/wdb.server.socket
    # systemctl enable wdb.server.socket
    # systemctl start wdb.server.socket

Next run:

    $ python -m wdb your_file.py

Wdb will open a debugging window right in your browser, paused at the beginning of your program.

You can access to http://localhost:1984/ to have an overview of the server.

NB: You have to start the server only once. Multiple Debugging sessions can be run simultaneously without problem.

This is not the only way to debug a program, see below.

Usage

Setting trace

To debug any program, with the server on, just add:

    import wdb
    wdb.set_trace()

anywhere in your code. Your program will stop at the set_trace line. (Just like pdb)

Tracing code

To inspect your code on exception, you can do the following:

    from wdb import trace
    with trace():
        wrong_code()

Any exception during wrong_code will launch a debugging session.

You can also use the start_trace() and stop_trace methods. (It's better to put the stop_trace in a finally block to avoid tracing all your program after an exception.)

Debugging web servers

wdb provides some tools to make it work nicely with different webservers:

Wsgi servers

For wsgi servers you can use the WdbMiddleware:

    from wdb.ext import WdbMiddleware
    wsgi_app = Whathever_wsgi_server_lib()
    my_app = WdbMiddleware(wsgi_app)
    my_app.serve_forever()
Flask

or using Flask:

    from flask import Flask
    from wdb.ext import WdbMiddleware
    app = Flask(__name__)
    app.debug = True
    app.wsgi_app = WdbMiddleware(app.wsgi_app)
    app.run(use_debugger=False) # Disable builtin Werkzeug debugger

you can also use the Flask-Wdb extension

    from flask import Flask
    from flask_wdb import Wdb

    app = Flask(__name__)
    app.debug = True
    Wdb(app)

    app.run()
Django

or using django:

Add the middleware in your wsgi.py:

After:

    from django.core.wsgi import get_wsgi_application
    application = get_wsgi_application()

Add this:

    from wdb.ext import WdbMiddleware
    application = WdbMiddleware(application)

And in your settings.py, activate exception propagation:

    DEBUG = True
    DEBUG_PROPAGATE_EXCEPTIONS = True
CherryPy

or using CherryPy:

import cherrypy
from wdb.ext import WdbMiddleware

class HelloWorld(object):
    @cherrypy.expose
    def index(self):
        undefined_method() # This will fail
        return "Hello World!"

cherrypy.config.update({'global':{'request.throw_errors': True}})
app = cherrypy.Application(HelloWorld())
app.wsgiapp.pipeline.append(('debugger', WdbMiddleware))

cherrypy.quickstart(app)

Tornado

In tornado, which is not a wsgi server, you can use the wdb_tornado function which will monkey patch the execute method on RequestHandlers:

    from wdb.ext import wdb_tornado
    from tornado.web import Application
    my_app = Application([(r"/", MainHandler)])
    if options.debug:
        wdb_tornado(my_app)
    my_app.listen(8888)

Page loading time become slow

If wdb slows down too much of your application (tracing all the things takes time), you can start it disabled with:

    my_app = WdbMiddleware(wsgi_app, start_disabled=True)  # or
    wdb_tornado(my_app, start_disabled=True)

Then when you get an exception just click on the on/off button.

Remote debugging

You can easily do remote debugging with wdb:

Let's say you want to run a program p.py on computer A and you want to debug it on computer B.

Start wdb server on computer A and launch this:

    WDB_NO_BROWSER_AUTO_OPEN=True python -m wdb p.py

And open a browser on computer B at the url given by wdb log.

Now you can also run wdb server on a computer C and run on computer A:

    WDB_NO_BROWSER_AUTO_OPEN=True WDB_SOCKET_SERVER=computerC.addr WDB_SOCKET_PORT=19840 python -m wdb p.py

And go with computer B to http://computerC/debug/session/[uuid in log] there you can step into p.py running in computer A. Yay !

You can use different configurations:

See wdb.server.py --help for changing ports on server and these environnement vars for wdb instances:

WDB_SOCKET_SERVER         # WDB server host
WDB_SOCKET_PORT           # WDB server socket port
WDB_WEB_SERVER            # WDB server host for browser openning
WDB_WEB_PORT              # WDB server http port
WDB_NO_BROWSER_AUTO_OPEN  # To disable the automagic browser openning (which can't be done if the browser is not on the same machine)

Docker

If you are developing locally with Docker, you can also use wdb to debug a code running inside a container. The basic setup looks like this:

  1. Start wdb.server.py running in a container and expose port 1984 to your host computer, this will server the debugging web server.
  2. Start debugging in your app container, making sure to set WDB_SOCKET_SERVER to the address of the server container, and point it to the expoed port 19840 on that server.
  3. When a trace is reached, open up http://<your-docker-hostname>:1984

I will walk through this process in detail, using Docker Compose to set up the containers.

Let's say your docker-compose.yml looks like their example for using with Django:

db:
  image: postgres
web:
  build: .
  command: python manage.py runserver 0.0.0.0:8000
  volumes:
    - .:/code
  ports:
    - "8000:8000"
  links:
    - db

Next lets add the wdb server part now and tell the web to link to it:

db:
  image: postgres
web:
  build: .
  command: python manage.py runserver 0.0.0.0:8000
  volumes:
    - .:/code
  ports:
    - "8000:8000"
  links:
    - db
    - wdb
  environment:
    WDB_SOCKET_SERVER: wdb
    WDB_NO_BROWSER_AUTO_OPEN: True
wdb:
  image: kozea/wdb
  ports:
    - "1984:1984"

And add wdb to your requirements.txt in your web app:

$ echo 'wdb' >> requirements.txt

Now we can use wdb.set_trace() in our python app.

# ... some code
import wdb
wdb.set_trace()

Then you have to rebuild your web application and start everything up again

$ docker-compose stop
$ docker-compose build web
$ docker-compose up

Now you can access http://<local docker server>:1984, to see the traces as they come up in your app.

In browser usage

Once you are in a breakpoint or in an exception, you can eval all you want in the prompt under the code. Multi-lines are partially supported using [Shift] + [Enter]. There is now help available by clicking on the top help button.

As of now the following special commands are supported during breakpoint:

* .s or [Ctrl] + [↓] or [F11]    : Step into
* .n or [Ctrl] + [→] or [F10]    : Step over (Next)
* .r or [Ctrl] + [↑] or [F9]     : Step out (Return)
* .c or [Ctrl] + [←] or [F8]     : Continue
* .u or [F7]                     : Until (Next over loops)
* .j lineno                      : Jump to lineno (Must be at bottom frame and in the same function)
* .b arg                         : Set a session breakpoint, see below for what arg can be*
* .t arg                         : Set a temporary breakpoint, arg follow the same syntax as .b
* .z arg                         : Delete existing breakpoint
* .l                             : List active breakpoints
* .f                             : Echo all typed commands in the current debugging session
* .d expression                  : Dump the result of expression in a table
* .w expression                  : Watch expression in current file (Click on the name to remove)
* .q                             : Quit
* .h                             : Get some help
* .e                             : Toggle file edition mode
* .g                             : Clear prompt
* .i [mime/type;]expression      : Display the result in an embed, mime type is auto detected on linux and defaults to "text/html" otherwise
* iterable!sthg                  : If cutter is installed, executes cut(iterable).sthg
* expr >! file                   : Write the result of expr in file
* !< file                        : Eval the content of file
* [Enter]                        : Eval the current selected text in page, useful to eval code in the source
*
* * arg is using the following syntax:
*   [file/module][:lineno][#function][,condition]
* which means:
*   - [file]                    : Break if any line of `file` is executed
*   - [file]:lineno             : Break on `file` at `lineno`
*   - [file][:lineno],condition : Break on `file` at `lineno` if `condition` is True (ie: i == 10)
*   - [file]#function           : Break when inside `function` function
*
* File is always current file by default and you can also specify a module like `logging.config`.

You can also eval a variable in the source by middle clicking on it. You can add/remove a breakpoint by clicking on the line number.

NB: Hotkeys with arrows are purposely not triggered in the eval prompt to avoid conflicts when typing.

Wdb Server

To see which debugging session are currently open, open your browser at http://localhost:1984/. You can also close crashed session.

From there you should also see all python process and their threads running and you can try to pause them during their execution to do step by step debugging and current variable inspection. This is highly experimental and requires gdb and a kernel with ptrace enabled to inject python code into a running python process. If you get ptrace: Operation not permitted. you will have to enable it.

Depending on your system it might work with:

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

Make sure that wdb is installed for the python version running the program too.

Importing wdb each time is exhausting

Yes to avoid that, you can add a w builtin at the beggining of your application:

    from wdb.ext import add_w_builtin
    add_w_builtin()

you can now use the w object any where in your code:

    my_code()
    w.tf  # Stop next line
    doubtful_code()
    my_code()
    with w.trace():
        doubtful_code()

Code completion

Wdb has dynamic code completion in eval prompt thanks to jedi.

FAQ

In Firefox opened debugging pages are not closed when done

It's a firefox config flag, visit about:config and set: dom.allow_scripts_to_close_windows to true

The logs are spammed with 'parsing Python module'

If your logging configuration is set to display DEBUG logs, you may see a log for every imported file in your project any time WDB is active, like so:

DEBUG 2017-07-16 13:15:03,772 index 49835 123145573191680 parsing Python module /project/.virtualenv/python-3.6.1/lib/python3.6/site-packages/package/file.py for indexing

To silence only this message, add a config for the importmagic module. For example:

LOGGING = {
    ...
    'loggers': {
        ...
        'importmagic.index': {
            'level': 'ERROR',
            'propagate': False,
        },
    },
}

Contribute

All contributions are more than welcomed, use the fork luke !

Or you still can use your money =)

Flattr gittip

Test

Wdb is now partially tested, so if you want to contribute be sure to run the test suite:

    $ pip install pytest
    $ pip install -e client -e server
    $ cd test
    $ py.test

Feel free to add tests !

Author

Florian Mounier @ Kozea

Licence

This library is licensed under GPLv3

wdb - An improbable web debugger through WebSockets

wdb Copyright (c) 2012-2016  Florian Mounier, Kozea

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

More Repositories

1

WeasyPrint

The awesome document factory
Python
7,017
star
2

Radicale

A simple CalDAV (calendar) and CardDAV (contact) server.
Python
3,262
star
3

pygal

PYthon svg GrAph plotting Library
Python
2,634
star
4

CairoSVG

Convert your vector images
Python
749
star
5

cairocffi

CFFI-based cairo bindings for Python.
Python
206
star
6

Pyphen

Hy-phen-ation made easy
Python
197
star
7

formol

An opinionated react form framework.
JavaScript
190
star
8

tinycss2

A tiny CSS parser
Python
159
star
9

Flask-WeasyPrint

Generate PDF files out of your Flask website thanks to WeasyPrint
Python
142
star
10

tinycss

tinycss is a complete yet simple CSS parser for Python.
Python
88
star
11

umlaut

Because a picture is worth a thousand words
JavaScript
56
star
12

cssselect2

CSS selectors for Python ElementTree
Python
27
star
13

flipflop

FastCGI/WSGI gateway
Python
25
star
14

sqlalchemy_fdw

A postgresql dialect based on psycopg2 adding support for Foreign Data Wrappers
Python
22
star
15

pygal.js

pygal javascript modules
JavaScript
15
star
16

log_colorizer

Defines a python logging formatter and a default handler for nice shell output
Python
13
star
17

weighted_mean

A simple weighted mean aggregate function for postgresql
C
12
star
18

brigit

A very simple python git wrapper module
Python
12
star
19

pystil

An elegant site web traffic analyzer
JavaScript
11
star
20

unrest

A troubling rest api library for sqlalchemy models
Python
9
star
21

tears

Flask SQLAlchemy single connection extension to run tests in a super transaction and rollback at teardown.
Python
9
star
22

mandrill-api-python-3.7

Python
8
star
23

WeasySuite

Test WeasyPrint with the W3C test suites
Python
8
star
24

pygal_maps_world

World maps for pygal
Python
7
star
25

gibolt

Git for Usain Bolt
Python
6
star
26

.git_hooks

A set of git hooks to use in our projects
Python
6
star
27

flask-alcool

ALCOOOL
Python
6
star
28

Pynuts

Documents for nuts
Python
6
star
29

Gedit-WhiteSpace-Terminator

Gedit 3 plugin that removes whitespace at the end of lines and files on saving.
Python
6
star
30

Ahem

A dummy font often used in W3C tests
5
star
31

PastaBin

A pastebin with taste
Python
5
star
32

docker-python-node-yarn-postgresql

Notre image docker
Dockerfile
5
star
33

pypet

Micro rolap engine based on sqlalchemy.
Python
4
star
34

Kozearch

Arch Linux packages made at Kozea
Shell
4
star
35

plainform

Formidable forms formed with WTForms
CSS
4
star
36

StructuredFS

Manage files in a structured directory hierarchy
Python
3
star
37

ymci

Your Modern Continuous Integration server
CSS
3
star
38

TeddyBar

Text edition toolbar
JavaScript
3
star
39

Koztumize

Dress your documents
Python
3
star
40

sitenco

Simple websites for simple projects.
Python
3
star
41

Dyko

A lightweight web framework
Python
3
star
42

CSStyle

CSStyle is an easy-to-use CSS converter for Webkit, Presto and Gecko. Experimental CSS values are converted to be understood correctly by browsers using these engines.
Python
3
star
43

WeasyPerf

Performance report for WeasyPrint
HTML
2
star
44

rrule34

Python dateutil rrule tools. Noticeably natural language formatting of recurences.
Python
2
star
45

pygal_maps_fr

French maps for pygal
Python
2
star
46

Overlay

Kozea's Gentoo Overlay
Shell
2
star
47

fdp

This project provides a web tool to work with pdf files (you can rotate or merge pdfs).
JavaScript
2
star
48

PDFormat

A Gtk-based PDF editor
Python
2
star
49

shoRTCut

WebRTC Websocket signalling client and server implementation
CSS
2
star
50

MakeCitron

Base Makefile for our projects
Makefile
2
star
51

SafetyNetwork

HTML
1
star
52

redux-api-unrest

Redux-api adapter and transformer for use with unrest.
JavaScript
1
star
53

RadicaleStorageByIndex

A regular radicale storage with an additional sqlite index on specified fields.
Python
1
star
54

misfile

A webcomic by Chris Hazelton, Misfile is the story of "a girl who was a boy, a Harvard-bound genius missing two years of her life, and the pot headed angel who did it to them" via a Celestial filing accident. In the small hillside town of Tempest, Massachusetts, Boy racer Ash was turned into a girl, studious Emily had the past two years of her life erased—including her admission to Harvard—and angelic loser Rumisiel was exiled to Earth for his incompetence. Fortunately, due to a side effect of the accident, only these three remember the universe-as-it-was. Lucky, because Rumisiel fears his superiors would likely 'correct' the misfile by making it permanent.
Python
1
star
55

pygal_sphinx_directives

Pygal sphinx integration
Python
1
star
56

x-files

A series revolving around FBI special agents Fox Mulder and Dana Scully who investigate X-Files
1
star
57

pygal_maps_ch

Swiss canton map for pygal
Python
1
star
58

medbox

A single box for your medicine
Python
1
star
59

wall-it

Python
1
star
60

passman

Password Manager
Python
1
star
61

for_da_win

C
1
star
62

docker-wdb-server

This project is abandoned
1
star
63

apparatus

Flask - Compass - Bootsrap - CoffeeScript - BuzzWord Bingo !
JavaScript
1
star
64

webpackozea

A base webpack config for our arch.
JavaScript
1
star
65

bobslide

Create and store reveal.js-based slideshows in the cloud
Python
1
star
66

Try-Multicorn

A browser based sql shell to show off multicorn features
Python
1
star
67

TimeRangeIndexedStorage

An attempt to optimize time range reports in radicale.
Python
1
star
68

sqlalchemy_psycopg_extensions

A set of sqlalchemy extensions designed for the psycopg2 database driver.
Python
1
star
69

emaj

E-Maj Postgresql extension.
PHP
1
star