我正在尝试将 bottle.py 作为脚本中的进程运行,但我感到沮丧,因为它没有按预期工作。 这是我脚本的假设/缩短表示。我试图添加尽可能多的评论。
magball.py
import serial
from bottle import route, run, template, request
import multiprocessing
import logging
import datetime
#Here are the most important variables which will be used in the entire script
global lastcommand #The last command received from bottle web interface
global status #What is the current status
lastcommand = 'Go Home' #Options: Start Drawing, Go Home, Next Drawing
status = 'home' #Options: home, homing (means going home), drawing
def log_this(level, msg)
#a special log function based on logging library for debugging
pass # <- details are not important, it is working fine
now = datetime.datetime.now()
timeString = now.strftime("%Y-%m-%d %H:%M")
info = {'title' : 'MAGBALL', 'time': timeString, 'lastcommand': lastcommand, 'status': status} #These are passed to main.tpl
@route('/', method='GET')
@route('/', method='POST')
def index(): #<- This works fine, passing the info to the template file (main.tpl) in views directory
global lastcommand #<- Isn't this referring to the global lastcommand declared at the beginning?
if request.method == 'POST':
lastcommand = request.forms.get("submit") #<- This works fine and lastcommand changes when the button on the web page is clicked
log_this('info', (lastcommand + ' clicked on web interface')) #<- I can see in the logs which button is clicked, so, this should mean
#that lastcommand (supposedly the global one) was changed successfully
return template('main.tpl', info)
p_bottle = multiprocessing.Process(target=run, kwargs=dict(host='0.0.0.0', port=80, debug='True')) #<- I start bottle as a process because I think I have to
p_bottle.daemon = True
def draw_pattern() #<- This function can easily run for hours which is fine/normal for the purpose
#Unless lastcommand is not equal to 'Start Drawing' this should run forever
global status
global lastcommand
status = 'drawing' #<- I think this should also refer to the global lastcommand declared at the beginning
#Opens a random file from a specific directory,
for filename in shuffled_directory:
#reads the file line by line and feeds it to the serial port
.
.
if lastcommand != 'Start Drawing': #<- This never works! Although I see in the logs that lastcommand was changed by index() function
log_this('warning', 'Last command changed during line feeding.')
break
def go_home()
global status
status = 'homing' #<- I think this should also refer to the global lastcommand declared at the beginning
#Send some commands to serial port and after that change the value of status
.
.
status = 'home'
while true: #This is the infinite loop that needs to run forever
global status #Don't these variables also refer to the global variables declared at the beginning?
global lastcommand
p_bottle.start() #The bottle.py web interface runs successfully
#The following while, if etc never runs. I think this "while true:" statement never gets notified
#that the values of lastcommand and/or status has changed
while lastcommand == 'Start Drawing':
if status == 'home':
draw_pattern()
if status == 'homing':
time.sleep(5)
if status == 'drawing':
pass
while lastcommand == 'Next Drawing':
if status == 'home':
draw_pattern()
if status == 'homing':
time.sleep(5)
if status == 'drawing':
go_home()
draw_pattern()
while lastcommand == 'Go Home':
if status == 'home':
pass
if status == 'homing':
pass
if status == 'drawing':
go_home()
main.tpl
<!DOCTYPE html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>Magball Web Interface</h1>
<h2>The date and time on the server is: {{ time }}</h2>
<h2>The last command is: {{ lastcommand }}</h2>
<h2>Status: {{ status }}</h2>
<form name='magballaction' method='POST'>
<input type="submit" name="submit" value="Start Drawing">
<input type="submit" name="submit" value="Go Home">
<input type="submit" name="submit" value="Next Drawing">
</form>
</body>
</html>
事情是这样的:
瓶子过程运行良好(网页是可访问的),当我单击网页上的按钮时,我在日志中看到 lastcommand 的值已被 Web 界面更改。
然而,末尾(while true:
)的无限循环永远不会收到 lastcommand 的值被更改的通知。因此,例如,如果状态 = home 和 last命令从 Web 界面更改为"开始绘图",则它不会执行draw_pattern()
。它什么都不做。
我试图将所有内容都放在def index()
函数中,放在return template('main.tpl', info)
行之前,但随后代码运行,但是 Web 界面等待代码完成才能启动。由于draw_pattern()
持续数小时,因此return template('main.tpl', info)
行实际上无法运行,并且无法访问网页。
我也尝试将def index()
作为正常功能运行,但是当我这样做时,唯一运行的是网络界面(def index()
)。
那么,我该怎么做才能通知 while 循环 lastcommand 和/或状态的值已更改?
对于任何感兴趣的人,我已经使用线程而不是多处理解决了这个问题。 所以不要使用它:
p_bottle = multiprocessing.Process(target=run, kwargs=dict(host='0.0.0.0', port=80, debug='True'))
p_bottle.daemon = True
我使用过:
p_bottle = threading.Thread(target=run, kwargs=dict(host='0.0.0.0', port=80, debug='True'))
p_bottle.daemon = True
现在线程中的函数可以成功更改全局变量,该变量立即被无限而真循环拾取。 感谢大家的建议。