如何从网页更改正在运行的Python脚本/服务中的变量?

时间:2022-03-02 12:16:15

I am using Raspbian on a Raspberry Pi. I have a Python script (LCD.py) that controls an LCD running as a service using supervisord.

我在Raspberry Pi上使用Raspbian。我有一个Python脚本(LCD.py),它使用supervisord控制作为服务运行的LCD。

I would like to able to enter a message on my web page and have it displayed on the LCD. I think this means I would have to change some variables that my LCD.py script reads, probably a flag to change mode and then the message itself using another Python script (CGI.py) executed by my server.

我希望能够在我的网页上输入一条消息并将其显示在液晶显示屏上。我想这意味着我必须更改我的LCD.py脚本读取的一些变量,可能是更改模式的标志,然后是使用我的服务器执行的另一个Python脚本(CGI.py)的消息本身。

What's the best way to do this? Or should I be doing something completely different? I think it is different from normal CGI type stuff as I cannot have a script being executed on each page load, it needs to run in the background (for scrolling, flashing etc)

最好的方法是什么?或者我应该做一些完全不同的事情?我认为它与普通的CGI类型的东西不同,因为我不能在每个页面加载时执行脚本,它需要在后台运行(用于滚动,闪烁等)

EDIT: Thanks for your help so far, I'll post my LCD daemon code tonight when i get home.

编辑:感谢您的帮助到目前为止,我将在今晚回家后发布我的LCD守护程序代码。

I have got a little further with this, I tried to use SimpleXMLRPCServer and threads, currently this dosn't work. I think its because threads don't actually run concurrently. This is my server code i was testing with:

我对此有所了解,我尝试使用SimpleXMLRPCServer和线程,目前这不起作用。我认为它是因为线程实际上并不同时运行。这是我测试的服务器代码:

    from SimpleXMLRPCServer import SimpleXMLRPCServer
    from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
    import threading
    import time

    globalMessage = "Hi, I havnt been changed!"

    # Restrict to a particular path.
    class RequestHandler(SimpleXMLRPCRequestHandler):
        rpc_paths = ('/RPC2',)

    # Create server
    server = SimpleXMLRPCServer(("localhost", 8000),
                                requestHandler=RequestHandler)
    server.register_introspection_functions()

    # Register an instance; all the methods of the instance are
    # published as XML-RPC methods (in this case, just 'div').
    class serverFunctions:
        def setMessage(self, message):
                global globalMessage
                globalMessage = message
                print(globalMessage)


    class serverThread(threading.Thread):
            def run(self):
                    server.register_instance(serverFunctions())

                    # Run the server's main loop
                    server.serve_forever()
                    print("test");

    class lcdThread(threading.Thread):
            def run(self):
                    global globalMessage
                    while(1):
                            oldMessage = globalMessage
                            if(oldMessage != globalMessage): print("Message has changed")
                            else: print ("Message has not changed")
                            print(globalMessage)
                            time.sleep(1)

    serverThread().start()
    #lcdThread().start()

and my client code:

和我的客户代码:

import xmlrpclib

s = xmlrpclib.ServerProxy('http://localhost:8000')


print s.setMessage("hello world")

If I un comment my lcdThread().start() line i think it is getting stuck in the lcd while loop and the server is not responding. Would multiProcessing make any difference? Please could you elaborate on the exec() function, how would i use exec() to change a global variable in a different script?

如果我取消注释我的lcdThread()。start()行我认为它会陷入lcd while循环并且服务器没有响应。 multiProcessing会有什么不同吗?请问你能详细说明exec()函数,我将如何使用exec()在不同的脚本中更改全局变量?

EDIT: Here is my LCD.py code that is a daemon, the message variable im trying to set is about half way down.

编辑:这是我的LCD.py代码,它是一个守护进程,我试图设置的消息变量大约是一半。

#!/usr/bin/python
from Adafruit_CharLCD import Adafruit_CharLCD
from subprocess import * 
from time import sleep, strftime
from datetime import datetime
from datetime import timedelta
from os import system
from os import getloadavg
from glob import glob
import RPi.GPIO as GPIO

#Variables
lcd = Adafruit_CharLCD() #Stores LCD object
cmdIP = "ip addr show eth0 | grep inet | awk '{print $2}' | cut -d/ -f1" #Current IP
cmdHD = "df -h /dev/sda1 | awk '{print $5}'" # Available hd space
cmdSD = "df -h / | awk '{print $5}'" # Available sd space
cmdRam = "free -h"
temp = 0

#Run shell command
def run_cmd(cmd):
    p = Popen(cmd, shell=True, stdout=PIPE)
    output = p.communicate()[0]
    return output

#Initalises temp device     
def initialise_temp():
    #Initialise
    system("sudo modprobe w1-gpio")
    system("sudo modprobe w1-therm")
    #Find device
    devicedir = glob("/sys/bus/w1/devices/28-*")
    device = devicedir[0]+"/w1_slave"
    return device

#Gets temp  
def get_temp(device):
    f = open (device, 'r')
    sensor = f.readlines()
    f.close()

    #parse results from the file
    crc=sensor[0].split()[-1]
    temp=float(sensor[1].split()[-1].strip('t='))
    temp_C=(temp/1000.000)
    temp_F = ( temp_C * 9.0 / 5.0 ) + 32

    #output
    return temp_C

#Gets time
def get_time():
    return datetime.now().strftime('%b %d  %H:%M:%S\n')

#Gets uptime
def get_uptime():
    with open('/proc/uptime', 'r') as f:
        seconds = float(f.readline().split()[0])
        array = str(timedelta(seconds = seconds)).split('.')
        string = array[0]
    return string

#Gets average load
def get_load():
    array = getloadavg()
    average = 0
    for i in array:
        average += i
    average = average / 3
    average = average * 100
    average = "%.f" % average
    return str(average + "%")

#def get_ram():
def get_ram():
    ram = run_cmd(cmdRam)
    strippedRam = ram.replace("\n"," ");
    splitRam = strippedRam.split(' ')
    totalRam = int(splitRam[52].rstrip("M"))
    usedRam = int(splitRam[59].rstrip("M"))
    percentage = "%.f" % ((float(usedRam) / float(totalRam)) * 100)
    return percentage + "%"

#Gets the SD usage
def get_sd():
    sd = run_cmd(cmdSD)
    strippedSD = sd.lstrip("Use%\n")
    return strippedSD

#Gets the HD usage
def get_hd():
    hd = run_cmd(cmdHD)
    strippedHD = hd.lstrip("Use%\n")
    return strippedHD

#This is the variable im trying to set  
#def get_message():
#   message = "hello"
#   return message

def scroll():
    while(1):
        lcd.scrollDisplayLeft()
        sleep(0.5)

#Message and IP - PERFECT
def screen1():
    ipaddr = run_cmd(cmdIP)
    lcd.message('Raspberry Pi\n')
    lcd.message('IP: %s' % (ipaddr))

#Uptime - tick
def screen2():
    uptime = get_uptime()
    lcd.message('Total Uptime\n') 
    lcd.message('%s' % (uptime))

#Ram and load - PERFECT
def screen3():
    ram = get_ram()
    lcd.message('Ram Used: %s\n' % (ram))
    load = get_load()
    lcd.message('Avg Load: %s' % (load))

#Temp and time - tick time
def screen4():
    time = get_time();
    lcd.message('Temp %s\n' % (temp))
    lcd.message('%s' % (time))

#HD and SD usage - PERFECT
def screen5():
    sd = get_sd()
    lcd.message('SD Used: %s\n' % (sd))
    hd = get_hd()
    lcd.message('HD Used: %s' % (hd))

#Web message    
#def screen6():
#   message = get_message()
#   lcd.message(message)

#Pause and clear
def screenPause(time):
    sleep(time)
    #In here to reduce lag
    global temp
    temp = str(get_temp(device));
    lcd.clear()
###########################################################################################################

try:
    #Initialise
    lcd.begin(16,2)
    device = initialise_temp()
    lcd.clear()

    #Main loop
    while(1):
        screen1()
        screenPause(5)
        screen2()
        screenPause(5)
        screen3()
        screenPause(5)
        screen5()
        screenPause(5)
        screen4()
        screenPause(5)

except KeyboardInterrupt:
    GPIO.cleanup()

Thanks Joe

2 个解决方案

#1


1  

If you're looking for a way to change a global variable while the script is running,

如果您正在寻找在脚本运行时更改全局变量的方法,

exec("<varname> = <newvar> in globals()")

If you don't post it in the comments.

如果您不在评论中发布。

EDIT: Maybe include any excisting code

编辑:可能包括任何激动人心的代码

#2


0  

If you need to send commands to LCD.py daemon; you could as well use http protocol to do it. You could try something like bottle to implement the web app part.

如果需要向LCD.py守护进程发送命令;你也可以使用http协议来做到这一点。您可以尝试像瓶子一样来实现Web应用程序部分。

You can run the web application as a separate daemon but you need to implement some form of IPC in LCD.py anyway.

您可以将Web应用程序作为单独的守护程序运行,但无论如何您需要在LCD.py中实现某种形式的IPC。

#1


1  

If you're looking for a way to change a global variable while the script is running,

如果您正在寻找在脚本运行时更改全局变量的方法,

exec("<varname> = <newvar> in globals()")

If you don't post it in the comments.

如果您不在评论中发布。

EDIT: Maybe include any excisting code

编辑:可能包括任何激动人心的代码

#2


0  

If you need to send commands to LCD.py daemon; you could as well use http protocol to do it. You could try something like bottle to implement the web app part.

如果需要向LCD.py守护进程发送命令;你也可以使用http协议来做到这一点。您可以尝试像瓶子一样来实现Web应用程序部分。

You can run the web application as a separate daemon but you need to implement some form of IPC in LCD.py anyway.

您可以将Web应用程序作为单独的守护程序运行,但无论如何您需要在LCD.py中实现某种形式的IPC。