Перезагрузка модуля Python при удаленном получении WebSocket

Я пытаюсь написать клиент веб-сокета Python, который может получать пользовательские сценарии и выполнять их.

Мой код выглядит так:

import config
import websocket
import time, ssl, json, importlib, sys
#when putting "import script" here def main is found, but not reloaded later on

script_loaded = False

def import_script(ws): #import/reload script module
    global script_loaded
    global script
    try:
        if script_loaded:
            importlib.reload(script)
        else:
            import script
            script_loaded = True
    except Exception as e:
        iot.report_error(ws, 'Loading Script', str(sys.exc_info()[0]), str(e))
        print('Error: ' + str(sys.exc_info()[0]) + ': ' + str(e))

class iot:
    def report_error(ws, place, etype, error):
        msg = json.dumps({"context": 3, "place": place, "type": etype, "error": error}, sort_keys=True)
        ws.send(msg)
    def write(ws, socket, data):
        msg = json.dumps({"context": 2, "socket": socket, "data": data}, sort_keys=True)
        ws.send(msg)
    def display(data):
        print(data)
    def start(ws): #start script module (def main)
        try:
            script.main(ws)
        except Exception as e:
            iot.report_error(ws, 'Executing Script (main())', str(sys.exc_info()[0]), str(e))
            print('Error: ' + str(sys.exc_info()[0]) + ': ' + str(e))


connectionEstablished = False
def on_message(ws, message):
    global connectionEstablished
    global script_loaded
    global script
    try:
        decoded_data = json.loads(message)
        if decoded_data['context'] == 0: #Log on
            connectionEstablished = True
        elif decoded_data['context'] == 1: #Receive Script
            if connectionEstablished:
                file = open('script.py','w')
                file.write("from iot_daemon import iot\n\n")
                file.write(decoded_data['script']) #write received script to file (works)
                import_script(ws) #import/reload script
                if script_loaded:
                    iot.start(ws) #start script module (def main)
    except Exception as e:
        print('Failed to process string: ' + str(e))

def on_error(ws, error):
    print('WebSocket Error: ' + error)

def on_close(ws):
    print("Closed.")

def on_open(ws):
    print("Connected.")
    msg = json.dumps({"context": 0, "type": 0, "key": config.key}, sort_keys=True)
    ws.send(msg)

if __name__ == "__main__":
    while True:
        if config.debugMode:
            websocket.enableTrace(True)
        ws = websocket.WebSocketApp(config.serverURL,
                                  on_message = on_message,
                                  on_error = on_error,
                                  on_close = on_close)
        ws.on_open = on_open
        ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
        time.sleep(5)
        print("Reconnecting...")

Хотя кажется, что получение скрипта работает (скрипт script.py обновляется при просмотре в текстовом редакторе), перезагрузка и выполнение новой версии не выполняется (всегда запускается версия скрипта, существующая при перезапуске или запуске клиента, или он вообще не запускает скрипт, если пропущен оператор импорта в верхней части скрипта).

Любая помощь приветствуется. Заранее спасибо.

1 ответ

Проблема на самом деле была довольно простой: Python не может перезагрузить модуль, который в данный момент открывается как FileObject. Поэтому простое добавление file.close() решило эту проблему.

Другие вопросы по тегам