11

Bokeh serve allows to write fast web apps with plots and widgets. How can I debug the python code when I use bokeh serve --show code.py?

Boern
  • 7,233
  • 5
  • 55
  • 86
Hanan Shteingart
  • 8,480
  • 10
  • 53
  • 66
  • For VS Code, check out [this example](https://gist.github.com/kylrth/148f061c1f4126dca2bd73cb9ad33007) I made. – Kyle Aug 13 '19 at 16:19

7 Answers7

9

Here's how I did it:

  1. Updated to Pycharm CE 2017

  2. At command prompt, run:

    $ which bokeh /Users/myname/envs/my_venv/bin/bokeh

  3. From menu selected : Run > Edit Configurations

  4. Entered the path from step 2 into "Script path:"

  5. Filled in "Parameters:" serve --show /full/path/to/viz.py --args myargs

This opened a browser window http://localhost:5006/viz and stopped at the breakpoint set inside viz.py

Hope that works for you

Giorgos Myrianthous
  • 36,235
  • 20
  • 134
  • 156
Paul Luteski
  • 91
  • 2
  • 4
6

I'm not really an IDE user, so I can't really say how to get things working with pycharm and the bokeh serve app.py way of running apps. However, as of 0.12.4 there is now guidance and examples for embedding a Bokeh server as a library. In particular you can create an app.py that you run in the "normal" way:

python app.py

My guess is that this way of doing things might work better with IDEs.

For reference, her is a complete "standalone script" embed:

import numpy as np
from tornado.ioloop import IOLoop

from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure
from bokeh.server.server import Server

io_loop = IOLoop.current()

def modify_doc(doc):
    x = np.linspace(0, 10, 1000)
    y = np.log(x) * np.sin(x)
    source = ColumnDataSource(data=dict(x=x, y=y))

    plot = figure()
    plot.line('x', 'y', source=source)

    slider = Slider(start=1, end=10, value=1, step=0.1)
    def callback(attr, old, new):
        y = np.log(x) * np.sin(x*new)
        source.data = dict(x=x, y=y)
    slider.on_change('value', callback)

    doc.add_root(column(slider, plot))

bokeh_app = Application(FunctionHandler(modify_doc))

server = Server({'/': bokeh_app}, io_loop=io_loop)
server.start()

if __name__ == '__main__':
    print('Opening Bokeh application on http://localhost:5006/')
    io_loop.add_callback(server.show, "/")
    io_loop.start()
bigreddot
  • 33,642
  • 5
  • 69
  • 122
  • Thanks @bigreddot. This actually still doesn't allow breakpoint inside modify doc but it saved me a lot of trouble solving other issues, e.g. joblib cache now works! (see http://stackoverflow.com/questions/41575567/bokeh-and-joblib-dont-play-together/41576000#41576000) – Hanan Shteingart Jan 10 '17 at 20:22
  • You can try breaking manually. I often add the line `import pdb; pdb.set_trace()` wherever I want to break. – bigreddot Jan 10 '17 at 21:12
  • can you please explain what's the difference between "standalone" and "torando" based? both seems to use Tornado. Moreover, can I use a class rather than a plain script in a function "modify_doc" – Hanan Shteingart Jan 15 '17 at 07:48
  • 1
    Yes they both use Tornado (Bokeh server *always* runs on a tornado `IOLoop`). The "standalone" examples shows how to embed just a bokeh server app by itself in a script. The "tornado" example shows how to embed a bokeh server app inside another, larger tornado app. – bigreddot Jan 15 '17 at 15:55
  • I have a bokeh server application in directory format. By modifying my main.py file as described above I can debug my scripts, but the rest of the directory content is ignored, like the templates. Any idea on how to make the above approach work for bokeh server applications from a directory? I've seen that the Server class has an argument called index (https://bokeh.pydata.org/en/latest/docs/reference/server/server.html#bokeh.server.server.Server), but whatever I specify there (".", "./templates", "/templates/index.html") it doesn't matter. – Gabor Aug 15 '19 at 22:03
  • You would have to make your own `FunctionHandler` subclass that implements all the same setup that [`DirectoryHandler.__init__`](https://github.com/bokeh/bokeh/blob/master/bokeh/application/handlers/directory.py#L114-L136) has for directories. – bigreddot Aug 15 '19 at 23:59
5

bokeh can also be run via python -m bokeh given that, you could open up the Run/Debug Configuration dialog and set your interpreter options to -m bokeh serve --show and your script will run as-is

tvt173
  • 1,746
  • 19
  • 17
  • Could you please elaborate? I do your way, but It looks like IDE skips -m flag... This is how it's calling python bokeh serve appUI "/Users/user/Library/Application Support/IntelliJIdea2016.3/python/helpers/pydev/pydevd.py" --multiproc --module --qt-support --client 127.0.0.1 --port 60102 --file python: can't open file 'bokeh': [Errno 2] No such file or directory – Dmitriy Apollonin Aug 17 '17 at 12:16
  • Unless you have a reason not to, try updating PyCharm to 2017.x, then set the "interpreter options" field in the run/debug config to "-m bokeh serve --show" (no quotes), as written above. I say upgrade pycharm because I think sometime around the switch to 2017.1, the run/debug config dialog had a major overhaul. The options were a bit different for <2016 (which I see you're using). Still possible, I believe, but I'd have to fire up the old version to say exactly what to do... – tvt173 Aug 18 '17 at 02:25
  • I tried this on Pycharm 2018.1 and running a bokeh server works fine. But when trying to debug the server application it gives an error about unrecognized arguments, which is OK, because bokeh tries to use the debug arguments given to python. Any idea on working around this problem? – Gabor Jul 25 '18 at 12:26
  • pycharm debugging doesn't work very well for bokeh server applications once it's on the server side of the application. so, what I usually do is set up two configs. one run config, setup as above. then, one debug config setup to run the script like a regular python script. that will give you debug capabilities for everything in the bootstrapping phase, but will exit before actually launching a server. to debug in the server, I fall back to good old console (logging) debugging, or calls to pdb, which will still actually work from the console, within the server threads – tvt173 Jul 25 '18 at 14:20
2

Another way is to run bokeh serve without arguments

bokeh serve

and push your app to the server. This allows you to debug the python script directly:

def update():
   ...

...
curdoc().add_periodic_callback(update,500)
session=push_session(curdoc())
session.show(plot)
session.loop_until_closed()

You will get a warning about push_session and loop_until_closed being discouraged. But for debugging purposes, it works well enough.

jpmorris
  • 882
  • 2
  • 10
  • 22
1

I found that you start the process in a process that already has the debugger attached to it, the debugger would be added there as well.

For example you can run the code below to do so

bokeh_process = subprocess.Popen(
['python', '-m', 'bokeh', 'serve', 'bokeh_server.py'], stdout=subprocess.PIPE)
1

I tried most of the above, but couldn't really get anything to run as intended, because I was getting error messages of missing imports with custom models. In the end, I got a working solution by running bokeh as a module in the IDE.

My specific IDE is PyCharm, so here is the process I employed:

  1. Go to Run > Edit Configurations
  2. Under Configuration, click on "Script path", and switch it to "Module name".
  3. As module name, enter bokeh
  4. As parameters, add "serve surface3d", where surface3d was the example that I tried to get running.
  5. Make sure your working directory is at the same location where you would normally have made the "bokeh serve" command.

This did the trick for me. Debugger hooks on, and the server can deal with custom models.

0

The approach that worked best for me was using the "Python Debug Server" run config within IntelliJ 2021.2.4, and following the instructions there: https://www.jetbrains.com/help/idea/run-debug-configuration-python-remote-debug.html

Using this approach I added the settrace method call in the runner of my Bokeh app:

pydevd_pycharm.settrace('localhost', port=28091, stdoutToServer=True, stderrToServer=True)

Then I was able to debug it from IntelliJ while serving the Bokeh app from the cmd line:

bokeh serve my_app --address 0.0.0.0 --port 28090
Steve
  • 33
  • 6