Can't get Bokeh server running with DirectoryHandler - python-3.x

I'm trying to get a bokeh server running with a DirectoryHandler.
The server seems to start but when I load the page in my browser it shows a blank page.
When I use a ScriptHandler and call the main.py directly everything works fine. The problem is that in this case the static directory is not recognized.
This does not work (DirectoryHandler):
from bokeh.application import Application
from bokeh.application.handlers import DirectoryHandler
from bokeh.server.server import Server
from tornado.ioloop import IOLoop
io_loop = IOLoop.current()
def create_bokeh_server(io_loop, file, port):
"""Start bokeh server with applications paths"""
bokeh_app = Application(DirectoryHandler(filename=file))
# kwargs lifted from bokeh serve call to Server, with created io_loop
kwargs = {
'io_loop': io_loop,
'port': port,
}
server = Server(bokeh_app,**kwargs)
return server
if __name__ == '__main__':
# create server
print('Create server')
bokeh_server = create_bokeh_server(io_loop=io_loop, file='C:/bokeh_app_dir/', port=8080)
# start bokeh server
print('Start bokeh server')
bokeh_server.start()
# start web server
print('Start Localhost')
io_loop.start()
This does work(ScriptHandler)
from bokeh.application import Application
from bokeh.application.handlers.script import ScriptHandler
from bokeh.server.server import Server
from tornado.ioloop import IOLoop
io_loop = IOLoop.current()
def create_bokeh_server(io_loop, file, port):
"""Start bokeh server with applications paths"""
bokeh_app = Application(ScriptHandler(filename=file))
# kwargs lifted from bokeh serve call to Server, with created io_loop
kwargs = {
'io_loop': io_loop,
'port': port,
}
server = Server(bokeh_app,**kwargs)
return server
if __name__ == '__main__':
# create server
print('Create server')
bokeh_server = create_bokeh_server(io_loop=io_loop, file='C:/bokeh_app_dir/main.py', port=8080)
# start bokeh server
print('Start bokeh server')
bokeh_server.start()
# start web server
print('Start Localhost')
io_loop.start()
where main.py is:
rom random import random
from bokeh.layouts import column
from bokeh.models import Button
from bokeh.models.widgets import CheckboxGroup, RadioGroup
from bokeh.palettes import RdYlBu3
from bokeh.plotting import figure, curdoc
# create a plot and style its properties
p = figure(x_range=(0, 100), y_range=(0, 100), toolbar_location=None)
p.border_fill_color = 'black'
p.background_fill_color = 'black'
p.outline_line_color = None
p.grid.grid_line_color = None
# add a text renderer to our plot (no data yet)
r = p.text(x=[], y=[], text=[], text_color=[], text_font_size="20pt",
text_baseline="middle", text_align="center")
i = 0
ds = r.data_source
# create a callback that will add a number in a random location
def callback():
global i
# BEST PRACTICE --- update .data in one step with a new dict
new_data = dict()
new_data['x'] = ds.data['x'] + [random()*70 + 15]
new_data['y'] = ds.data['y'] + [random()*70 + 15]
new_data['text_color'] = ds.data['text_color'] + [RdYlBu3[i%3]]
new_data['text'] = ds.data['text'] + [str(i)]
ds.data = new_data
i = i + 1
def update():
"""Example of updating plot on radio button change"""
if radio_group.active == 0:
p.border_fill_color = 'black'
p.background_fill_color = 'black'
elif radio_group.active == 1:
p.border_fill_color = 'white'
p.background_fill_color = 'white'
else:
p.border_fill_color = 'blue'
p.background_fill_color = 'blue'
# add a button widget and configure with the call back
button = Button(label="Press Me")
button.on_click(callback)
# add group of radio butt
radio_group = RadioGroup(
labels=['black', 'white', 'blue'],
active=0
)
radio_group.on_change('active', lambda attr, old, new: update())
# put the button and plot in a layout and add to the document
curdoc().add_root(column(radio_group, button, p))
What am I missing here?
I need the static directory for images I want to load.

Good working example! I am struggling to recreate though. I ran your code exactly on Windows, Python3.7 and bokeh 1.3.1 and bokeh server launches the app on http://localhost:8080/.
Some things to try:
Where and how are you executing the calling script (the scripts where the only difference is DirectoryHandler or ScriptHandler)? I put mine in a separate run.py and just ran it with "python run.py". run.py can but doesn't have to be in the top level app folder. It runs with main.py as the only file in my top level app folder.
What are outputs of python console logging?
What are outputs of your browsers developer tab (usually F12)? I do get an error that Tornado can't find the favicon.ico file (lil browser thumbnail image)
If you take a look at the Bokeh library code for the DirectoryHandler it doesn't do much beyond decorating the ScriptHandler!
https://docs.bokeh.org/en/latest/_modules/bokeh/application/handlers/directory.html#DirectoryHandler

Related

Ubuntu 22.04: pyautogui.locateOnScreen is returning None. How to solve this?

My OS is Ubuntu 22.04, Python 3.10.4.
I am trying to create a code to automate Whatsapp send message.
Have installed latest version of pyautogui.
Following is the code I am running:
import pyautogui as pt
import paperclip as pc
# from pynput.mouse import Controller, Button
from time import sleep
# mouse = Controller()
class WhatsApp:
def __init__(self, speed=5, click_speed=.3):
self.speed = speed
self.click_speed = click_speed
self.message = ''
self.last_message = ''
def nav_green_dot(self):
try:
# position = pt.locateOnScreen('clip_pic.png', confidence = .7)
# position = pt.locateOnScreen('clip_pic.png')
# print(position)
print(pt.locateOnScreen('clip_pic.png'))
# pt.moveTo(position[0:2], duration = self.speed)
# pt.moveRel(-100, 0, duration = self.speed)
except Exception as e:
print ('Exception (nav_green_dot): ', e)
wa_bot = WhatsApp(speed = .5, click_speed = .4)
sleep(5)
wa_bot.nav_green_dot()
At print(pt.locateOnScreen('clip_pic.png')) I am getting None.
Attached is the picture I am trying to capture.
I have already opencv-python installed as well.
I also have whatsapp web page opened in a chrome browser.
I tested in firefox as well.
The output error is not clear in what direction I should go.
What am I missing?
Finding image on screen for only one time may be None you need to check repeatedly for it. And if it is found you can end the loop you are using to find it. You should use python's multithreading for it. here is an updated version of your code
import pyautogui as pt
import paperclip as pc
# from pynput.mouse import Controller, Button
from time import sleep
import threading
# mouse = Controller()
FOUND_IMAGE = False
def checkFunction():
global FOUND_IMAGE
while True:
img = pt.locateOnScreen('img.png')
if img != None:
FOUND_IMAGE = True
break
checkThread = threading.Thread(target=checkFunction) # creating therad
checkThread.start() # starting therad
class WhatsApp:
def __init__(self, speed=5, click_speed=.3):
self.speed = speed
self.click_speed = click_speed
self.message = ''
self.last_message = ''
def nav_green_dot(self):
try:
# position = pt.locateOnScreen('clip_pic.png', confidence = .7)
# position = pt.locateOnScreen('clip_pic.png')
# print(position)
print(FOUND_IMAGE)
# pt.moveTo(position[0:2], duration = self.speed)
# pt.moveRel(-100, 0, duration = self.speed)
except Exception as e:
print ('Exception (nav_green_dot): ', e)
wa_bot = WhatsApp(speed = .5, click_speed = .4)
sleep(5)
wa_bot.nav_green_dot()
For any queries have a look at this question or this Post

Flask versus PyQt5 - Flask controls program flow?

Flask appears to prevent PyQt5 UI from updating.
The respective code works properly for either PyQt5 or Flask - but not together. I understand that it may need to do with the way threading is set up.
Any assistance would be greatly appreciated. TIA.
`
import sys
import serial
import threading
from PyQt5.QtWidgets import QWidget, QLabel, QApplication
from flask import Flask, render_template, request, redirect, url_for
app1 = Flask(__name__)
ser = serial.Serial ("/dev/ttyS0", 57600,timeout=3) #Open port with baud rate
count=0
temp = []
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
global count
count = 1
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('PyQt5 vs Flask')
self.lbl1 = QLabel('Count '+str(count), self)
self.lbl1.move(100, 50)
self.show()
threading.Timer(5,self.refresh).start()
def refresh(self):
global count
count +=1
print("UI ",count)
self.lbl1.setText('Count'+str(count))
threading.Timer(5,self.refresh).start()
def get_uart():
global temp
if ser.inWaiting()>0:
temp =[str(float(x.decode('utf-8'))) for x in ser.read_until().split(b',')]
print(temp)
threading.Timer(1,get_uart).start()
#app1.route("/")
def index():
global temp
templateData = {'temp1' : temp[1] ,'temp2' : temp[2]}
return render_template('index.html',**templateData)
if __name__ == "__main__":
app = QApplication(sys.argv)
pyqt5 = Example()
threading.Timer(1,get_uart).start()
ser.flushInput()
#app1.run(host='0.0.0.0',threaded=True, port=5000) # ,debug=True)
sys.exit(app.exec_())
`
Need to have a UI to control the data analysis to be displayed on Website.
[SOLVED]
All Flask parameters can be defined as:
port = int(os.environ.get('PORT', local_port))
kwargs = {'host': '127.0.0.1', 'port': port , 'threaded' : True, 'use_reloader': False, 'debug':False}
threading.Thread(target=app.run, daemon = True, kwargs=kwargs).start()
and Flask will NOT Block and run with the parameters defined in kwargs.
The better way deal with (possibly waiting) processes, is to use Qt's own threads.
In this example I've created a QObject subclass that does all processing and eventually sends a signal whenever the condition is valid. I can't install flask right now, so I've not tested the whole code, but you'll get the idea.
The trick is to use a "worker" QObject that does the processing. Once the object is created is moved to a new QThread, where it does all its processing without blocking the event loop (thus, the GUI).
You can also create other signals for that object and connect to your slots (which might also be standard python functions/methods outside the QtApplication) which will be called whenever necessary.
class Counter(QtCore.QObject):
changed = QtCore.pyqtSignal(str)
def __init__(self):
super().__init__()
self.count = 0
def run(self):
while True:
self.thread().sleep(1)
if ser.inWaiting() > 0:
self.changed.emit('{}: {}'.format(self.count, [str(float(x.decode('utf-8'))) for x in ser.read_until().split(b',')]))
self.count += 1
class Example(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.counter = Counter()
self.counterThread = QtCore.QThread()
self.counter.moveToThread(self.counterThread)
self.counterThread.started.connect(self.counter.run)
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('PyQt5 vs Flask')
self.lbl1 = QtWidgets.QLabel('Count {}'.format(self.counter.count), self)
self.lbl1.move(100, 50)
self.counter.changed.connect(self.lbl1.setText)
self.counterThread.start()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
pyqt5 = Example()
pyqt5.show()
I think the problem stems from how Flask is activated. If the app.run command is given any parameters (even if in a Thread), then it blocks other commands.
The only way I was able to make Flask and PyQt5 work at the same time, was to activate Flask in a dedicated Thread WITHOUT any parameters - SEE BELOW for the various combinations.
Question: Is this a Flask/Python Bug or Feature or some other explanation related to Development vs Production deployment??
In any case, I would like any help with finding a way to deploy flask in a Port other than 5000 - WITHOUT Flask Blocking other code.
import sys
import serial
import threading
import atexit
from PyQt5.QtWidgets import QWidget, QLabel, QApplication
from flask import Flask, render_template, request, redirect, url_for
ser = serial.Serial ("/dev/ttyS0", 57600,timeout=3) #Open port with baud rate
app = Flask(__name__)
count=0
temp = []
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
global count
count = 1
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('PyQt5 vs Flask')
self.lbl1 = QLabel("Count "+str(count)+" ", self)
self.lbl1.move(100, 50)
self.show()
threading.Timer(5,self.refresh).start()
def refresh(self):
global count
global str_data
count +=1
self.lbl1.setText("Count "+str(count)+" ")
threading.Timer(0.5,self.refresh).start()
def get_uart():
global temp
if ser.inWaiting()>0:
temp =[str(float(x.decode('utf-8'))) for x in ser.read_until().split(b',')]
print(temp)
threading.Timer(1,get_uart).start()
#app.route("/")
def blank():
global count
data="Count "+str(count)
return data
if __name__ == "__main__":
threading.Timer(5,get_uart).start()
#app.run ## Does not block further execution. Website IS NOT available
#app.run() ## Blocks further execution. Website available at port 5000 without Refresh value
#app.run(port=5123) ## Blocks further execution. Website available at port 5123 without Refresh value
#app.run(threaded=True) ## Blocks further execution. Website available at port 5000 without Refresh value
#threading.Thread(target=app.run()).start() ## Blocks further execution. Website available at port 5000 without Refresh value
#threading.Thread(target=app.run(port=5123)).start() ## Blocks further execution. Website available at port 5123 without Refresh value
#threading.Thread(target=app.run(threaded=True)).start() ## Blocks further execution. Website available at port 5000 without Refresh value
threading.Thread(target=app.run).start() ## Flask DOES NOT block. Website is available at port 5000 with Refresh value
print("Flask does not block")
app1 = QApplication(sys.argv)
pyqt5 = Example()
sys.exit(app1.exec_())

I am unable to simultaneously stream the feed from my RBP3's camera and record to a file at the same time using python

I know how to save to a file using the code below (and timestamp the feed) and I know how to stream using uv4l but I am simply too bad to do it simultaneously.
import time
time.sleep(60)
import picamera
import datetime as dt
camera = picamera.PiCamera()
camera.resolution = (640, 480)
#camera.vflip = True
camera.led = False
x = 0
while True:
bideoname = "/media/pi/cam/" + dt.datetime.now().strftime('%Y-%m-%d-%H') + ".h264"
camera.annotate_background = picamera.Color('black')
camera.annotate_text = dt.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
#camera.start_preview()
camera.start_recording(bideoname)
start = dt.datetime.now()
while (dt.datetime.now() - start).seconds < 3600:
camera.annotate_text = dt.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
camera.wait_recording(0.2)
camera.stop_recording()
x = x+1
I imagine I would use flask to to create local website to stream the feed to.
I have looked up and down the internets and this example seems to be the closest solution by Dave Jones but I don't if socket can communicate with a browser:
https://raspberrypi.stackexchange.com/questions/27041/record-and-stream-video-from-camera-simultaneously
Also there is this code which streams the camera feed to a page but no mention of how to simultanously record as well:
from flask import Flask, render_template, Response
# Raspberry Pi camera module (requires picamera package, developed by Miguel Grinberg)
from camera_pi import Camera
app = Flask(__name__)
#app.route('/')
def index():
"""Video streaming home page."""
return render_template('index.html')
def gen(camera):
"""Video streaming generator function."""
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
#app.route('/video_feed')
def video_feed():
"""Video streaming route. Put this in the src attribute of an img tag."""
return Response(gen(Camera()),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
app.run(host='0.0.0.0', port =80, debug=True, threaded=True)
Or maybe this is all wrong and there is simpler solution to this?
Thanks for the help.

bokeh server app returns blank screen

I am trying to render a simple app on bokeh server. I took the script straight from the bokeh website.
# myapp.py
from random import random
from bokeh.layouts import column
from bokeh.models import Button
from bokeh.palettes import RdYlBu3
from bokeh.plotting import figure, curdoc
# create a plot and style its properties
p = figure(x_range=(0, 100), y_range=(0, 100), toolbar_location=None)
p.border_fill_color = 'black'
p.background_fill_color = 'black'
p.outline_line_color = None
p.grid.grid_line_color = None
# add a text renderer to our plot (no data yet)
r = p.text(x=[], y=[], text=[], text_color=[], text_font_size="20pt",
text_baseline="middle", text_align="center")
i = 0
ds = r.data_source
# create a callback that will add a number in a random location
def callback():
global i
# BEST PRACTICE --- update .data in one step with a new dict
new_data = dict()
new_data['x'] = ds.data['x'] + [random()*70 + 15]
new_data['y'] = ds.data['y'] + [random()*70 + 15]
new_data['text_color'] = ds.data['text_color'] + [RdYlBu3[i%3]]
new_data['text'] = ds.data['text'] + [str(i)]
ds.data = new_data
i = i + 1
# add a button widget and configure with the call back
button = Button(label="Press Me")
button.on_click(callback)
# put the button and plot in a layout and add to the document
curdoc().add_root(column(button, p))
I run this in my Win Python Command Prompt.exe using the below:
python -m bokeh serve --show main.py
This runs the app, but I am left with a blank webpage. See the output in the command prompt below:
Can anyone help with how to get this to show the doc?

BottlePy and PyWebView

I am trying to build a small app in Bottle, and thought I'd try using pywebview as a viewer. When I run the following file, I get two instances of the webview window. The first one shows the page, the second shows a spinning wheel cursor. Closing the second window is shutting down the web server, I believe, but not killing the thread.
Why are there two windows showing up?
import sys
import threading
from bottle import Bottle, ServerAdapter
import webview
class MyWSGIRefServer(ServerAdapter):
server = None
def run(self, handler):
from wsgiref.simple_server import make_server, WSGIRequestHandler
if self.quiet:
class QuietHandler(WSGIRequestHandler):
def log_request(*args, **kw): pass
self.options['handler_class'] = QuietHandler
self.server = make_server(self.host, self.port, handler, **self.options)
self.server.serve_forever()
def stop(self):
# self.server.server_close() <--- alternative but causes bad fd exception
self.server.shutdown()
app = Bottle()
listen_addr = 'localhost'
listen_port = 8080
server = MyWSGIRefServer(host='localhost', port=8080)
#app.route('/')
def hello():
return "Hello World!"
def start_server():
app.run(server=server, reloader=True)
try:
print(threading.enumerate())
serverthread = threading.Thread(target=start_server)
serverthread.daemon = True
print("starting web server")
serverthread.start()
print("starting webview")
webview.create_window('bottle test', "http://localhost:8080/")
print("webview closed. closing server")
sys.exit()
server.stop()
except Exception as ex:
print(ex)
The issue was using reloader=True when running the server. Setting this to False prevents the second window from appearing.

Resources