Desenho sem bloco e atualização de gráficos com bokeh

imagem

Eu tenho um script Python com cálculos. Houve um ciclo de cerca de 2000 iterações, sendo cada uma delas considerada por alguns minutos.

E decidi depurar inteligentemente esse script, exibir um gráfico de algumas métricas a partir do número da iteração. E, como a próxima iteração é calculada, esse agendamento e atualização.

A maneira mais fácil de fazer isso é com bokeh. Mais precisamente, usando um servidor bokeh para desenhar gráficos. Como - agora vou lhe contar.

Primeiro, inicie o servidor: o servidor sai da caixa junto com o próprio bokeh; portanto, após o pip instalar o bokeh, basta digitar bokeh serve no console e o servidor é iniciado.

Por que é necessário? E então para mostrar os gráficos

  • não bloqueou a execução do restante do código (porque isso acontece no navegador, em um processo separado),
  • para que o gráfico responda ao redimensionamento da janela (ou à minimização-maximização)
  • e para que, a qualquer momento, possamos alterar esse cronograma como quisermos, diretamente do nosso processo Python!

Isso é feito assim:

import time import sys from bokeh.plotting import figure from bokeh.client import pull_session from bokeh.models import ColumnDataSource #     --    -,    bokeh serve # Please run "bokeh serve" in console before start! if __name__ == "__main__": #    (  ,     ) session = pull_session() #  .. ,      (    ) fig = figure(title=("Total TBS (in bits)"), plot_height=300, plot_width=800) #         datasource = ColumnDataSource(data={"x": [], "y": []}) line = fig.line(x="x", y="y", source=datasource, line_width=2, legend=("Super dooper line from hell")) #        session.show(fig) #     for i in range(10000): #          .   datasource     #       = ) datasource.stream({"x": [i], "y": [i ** 2]}) #       30-40      ,   session.force_roundtrip() #  ! 

Anteriormente, eu também tinha que fazer isso, mas as decisões anteriores eram, para dizer o mínimo, não tão boas. O que eu não tentei na minha vida ...

Cuidado, lastro cerebral!
Você pode usar o matplotlib no modo sem bloqueio, puxando manualmente plt.draw () a cada iteração. É verdade que o matplotlib não possui seu próprio processamento de mensagens da GUI no modo sem bloqueio e, se a janela minimizar ou fechar com outra janela, devemos aguardar a próxima iteração para redesenhar. So-so muleta, mas para depuração ele vai fazer.

É possível no Negro gerar uma imagem com um gráfico do mesmo matplotlib e despejá-la no disco. Também uma muleta feroz, mas um passeio pela falta de peixe. Ou em uma máquina remota sem gráficos.

Você pode fazer isso de uma maneira interessante: use PyQt, agrupe o código de cálculo em um QObject, envie-o para um fluxo separado, agrupe os gráficos matplotlib em um QWidget (ou use os gráficos do Qt Data Visualizaion ou do PyQtGraph), conecte a matemática aos gráficos por meio de um sinal com um slot , e haverá felicidade. É verdade que isso é um pouco como uma solução de depuração rápida, e o Qt precisa ser ensinado, mas eu fiz isso algumas vezes.

Você pode criar um aplicativo de servidor pequeno para desenhar gráficos em um processo separado (por exemplo, usando aiohttp + PyQt + PyQtGraph), que pode ser eliminado da API REST no processo principal. Uma vez eu fiz isso, mas também não atraiu a correção rápida para depuração.

Você pode escrever em algum tipo de banco de dados (o que está na moda no momento?) E depois deixar o Grafan entrar na moda. É verdade que você precisa colocar o banco de dados e o Grafan, configurá-los e geralmente se incomoda em escrever no banco de dados. Provavelmente, também é possível através de um arquivo, mas para dois gráficos com mil pontos cada um é como um pardal de armas ...

Ou você pode entender plotly.dash, colocar a matemática em um fluxo separado, envolvê-lo em um aplicativo de traço e fazer um monte de lixo. Isso eu não dominei, embora fosse necessário.

Em suma, depuração bem-sucedida!

Source: https://habr.com/ru/post/pt474378/


All Articles