Developping a panel app - dev tools for being efficient at it?

Hi,

I’ve been playing with panel for a while and think it’s a very useful librairy :slight_smile:.

But after a while, I was wondering, what are the best tools that one could use to efficiently develop a panel app?

Jupyter Notebook? Jupyter Lab? VS Code? Spyder? Some other IDE? A combination of those?

I find Notebooks to be super useful for quick prototyping, discovering how the library works, but I have the feeling that for bigger, more complex apps they hinder the development process. On the other hand, I’ve been trying to use VS Code with my app saved in one or several Python scripts (*.py) and running them with python -m bokeh serve --dev myapp.py. This is OK but I miss what I had with Jupyter, i.e. the possibility to interact with the objects I’ve created to better understand what I’m doing (also because I’d say that I’m a panel beginner).

Could you then share with which tools and how you develop your apps?

In the end, developing a GUI app isn’t something that is trivial when the app becomes complex. It’d be awesome to have a guide providing the best practices and tools that one could use to develop and debug a panel app :slight_smile:

I don’t want to forget to mention that Marc has published some docs about how to use VS Code for developing an app with panel.

Thanks!

3 Likes

Hi @MaximIt

This is really a good question. Or at least its also one that concerns me a lot.

Here are my current thoughts

  1. As a beginner I would start out in a Notebook. It provides very fast feedback.
    • One problem though is that sometimes there are errors that only shows up in the browser console. I.e. you need to open that using CTRTL+SHIFT+I. Here Streamlit has a nicer way of working because it provides the error directly in the app it self. This helps beginners a lot.
    • I know @philippfr works in jupyterlabs. I’ve also thought about moving to that. But I actually don’t use Notebooks that much my self. But I have been starting because they are great for documentation.
    • One of the reasons that I’m very interested in Panel is that it supports the largest range of use cases from Notebook over Panel server and into Flask/ Django servers. That is really, really strong. I can build dashboards and small apps for “simple” users. But the same apps can be used by “advanced” users in Notebooks where they can use it to filter some data and then access the data directly in the Jupyter Notebook. That is very similar to how people work in Excel. Excel is a mix of Data and UI. And users can change/ improve the UI on the day if they need it.
  2. Later I would move to my favourite editor/ IDE. For me that is VS Code. And as my code/ app starts to grow I would seperate it into different files or folders. Something like
  • model: (Very simple model class descending from `param.Parameterized). Might have simple functions like str, repr, repr_html, to_dict,from_dict etc.
  • services: Extract, Transform and/ or Load functions. For example functions for getting data from databases or transforming a list of models (maybe via DataFrames).
  • plots: Seperate library for plotting. As its just handy and enables seperation of HoloViews, Plotly, Altair plots etc.
  • components: These are small, atomic, reusable Panel components that uses models, services and plots. For example a small component of dropdown for filtering some dataframe. The DataFrame might be included in the component or not.
  • apps: composed of multiple components.

One issue when working with python -m panel serve 'app.py' --dev --show is that the server reloads but it relatively slow. See https://github.com/bokeh/bokeh/issues/9501. So slowing down the development cycle. An alternative is to write the code in .py files but visually test in a Notebook and use importlib.reload to road the code easily. Sometimes this works great. But not always.

One great thing of the above layering is that its pretty easy to write smaller tests. Panel is actually great in that sense at you only have to use the Python test frameworks like pytest - even for functional tests. No need to learn or use javascript testing frameworks. I don’t think they are great.

Looking forward to other ideas and thoughts below.

2 Likes

Hi Marc and thanks for your thorough answer.

The app I’m trying to build is actually a replacement of an Excel spreadsheet. Building a UI interface with panel made me realize how simple it is to build a simple GUI app with Excel that is easy to share (just copy paste it wherever you want :wink: ) and that is going to preserve its state for basically forever (pretty sure I’ll be able to open a .xlsx file in 10 years). Yet, panel allows me to add that interactivity that I missed with Excel, it’s also more fun to work with!

I’ve also found out that some errors only show up in the browser console. It took me a while though as I know pretty much nothing about web dev. I see using panel (powered by bokeh) as a gentle way to slowly dive into more web dev (javascript, html, css) and understanding how servers work.

Jupyter Lab with its integrated terminal seems a little better than the more classic Notebook interface when it comes to developping an app. Last time I tried (a while ago!) things didn’t work out of the box so I just postponed using it. Maybe it’s time.

Thanks a lot for the details about the architecture of your apps. Would you have a concrete example to share?

Thanks again Marc, I hope more people will join in to share what set up they have :slight_smile:

1 Like

Project Jupyter has just announced here the release of an integrated debugger for JupyterLab. They mention that they’d like to add the possibility to debug Voila apps with that tool. This is great ! I hope panel will be able to benefit from that.

1 Like

The way I develop panel applications in vs code is to add the following command in my launch.json. This enable to use the native vs code debug tools. I think it is more elegant than what is mentioned on awesome-panel, but I could be wrong :slight_smile:

{
    "name": "Python: Panel",
    "type": "python",
    "request": "launch",
    "module": "panel",
    "args": [
        "serve",
        "${file}",
    ],
}

You’re absolutely right. It is now straightforward to debug with VS Code. It has changed and the guide should change :slight_smile:

5 Likes

Wow how did I miss that! Thanks a lot @Hoxbro, that is super handy!

1 Like

@Hoxbro Would you mind either starting an issue or even a PR that adds a notebook to the user guide to talks about effective development and debugging practices?

Sure! I will start with an issue, as I don’t know when I will have time for the PR myself.

1 Like

I sometimes have an issue where I run my panel app from python/pycharm and I get an ‘exit code 1’ with no further debugging information.

I found this trick very helpful to get the traceback in these cases:


if __name__ == '__main__':
    sys._excepthook = sys.excepthook

    import traceback as tb
    def my_exception_hook(exctype, value, traceback):
        # Print the error and traceback
        tb.print_tb(traceback, file=sys.stdout)
        print(exctype, value, traceback)

        tb.print_stack()
        print(traceback.format_exc())
        # or
        print(sys.exc_info()[2])
        # Call the normal Exception hook after
        sys._excepthook(exctype, value, traceback)
        sys.exit(1)


    # Set the exception hook to our wrapping function
    sys.excepthook = my_exception_hook

    pn.serve(app})

(I think i got this from here: python - PyQt5 fails with cryptic message - Stack Overflow)

This is a great summary! Do you have some references/guides to follow on? I would like to modularize my notebooks where I have done some analysis+panel dashboard and would like to adapt to a code structure that you mentioned above in point 2. Would be nice to see some examples or read some references to start with. @Marc

Hi @Hoxbro

Which configuration are you using today? If I try

{
    "name": "Python: Panel",
    "type": "python",
    "request": "launch",
    "module": "panel",
    "args": [
        "serve",
        "${file}",
    ],
}

Then it runs the file as a python file. It does not work.

This one works for me

{
            "name": "panel serve",
            "type": "python",
            "request": "launch",
            "program": "-m",
            "args": [
                "panel",
                "serve",
                "${file}"
            ],
            "console": "integratedTerminal",
            "justMyCode": true
        },
1 Like