简体   繁体   中英

How to change a variable in a running Python script/service from a web page?

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.

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.

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)

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

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:

    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?

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

#!/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

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

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM