python-shell节点,保留一个python脚本运行

python-shell node, keep a python script running

有人知道在使用 python-shell 时是否可以在从 Javascript 调用时保留 python 脚本 运行ning 吗?也许使用 python-shell?

从 Javascript 从 Python class 调用方法

例如,此代码有效,但每次调用时都会终止 Python 脚本。

let {PythonShell} = require("python-shell");

let options = {
  mode: "text",
  args: ["read", "12345:2", "analogInput", "2"],
};

PythonShell.run("bac0Worker.py", options, function (err, results) {
  if (err){
    console.log(err)
    console.log("An error happened")
  }else{
      // results is an array consisting of messages collected during execution
    console.log("results: ", results);
    console.log("Python Script Finished");
    }
})

在 Python 方面,我正在为 BACnet 系统试验一个名为 BAC0 的包。我想做的是弄清楚我是否可以保留 BAC0 脚本 运行ning,我认为在 BAC0 的引擎盖下有很多过程正在进行,如果脚本 started/stopped 很多。

bac0Worker.py

import sys
import BAC0

BAC0.log_level('silence')
bacnet = BAC0.lite()


def do_things(address,object_type,object_instance):
        try:
            read_vals = f'{address} {object_type} {object_instance} presentValue'
            read_result = bacnet.read(read_vals)
            if isinstance(read_result, str):
                pass
            else:
                read_result = round(read_result,2)
            print(read_result)
        except Exception as error:
            print("read error")


def main():
    # args from Javascript
    first = sys.argv[1]
    second = sys.argv[2]
    third = sys.argv[3]
    fourth = sys.argv[4]

    # get sensor data
    do_things(second, third, fourth)

    # all done    
    bacnet.disconnect()



if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("bacnet app error")
        bacnet.disconnect()

就像我提到的,如果我从 Node 运行 我可以看到来自 BACnet 网络的传感器值 71.7 度,代码就可以工作。

C:\Program Files\nodejs\node.exe .\start.js
results:  (1) ['71.7']
Python Script Finished

希望这是有道理的,很抱歉提出这个奇怪的问题,但很好奇是否有人对如何保留 Python 脚本 运行ning 有任何提示,然后我可以在其中传递值(传感器和设备寻址信息)到 BAC0 脚本以请求从网络读取 BACnet。在 Python 文件的主要功能中,如果我替换为:

# all done    
bacnet.disconnect()

与:

while True:
    pass

这将使 Python 文件保持活动状态 我只是不知道如何使用 python-shell 将值传递给活动的 Python 脚本。感谢您提供的任何提示,这里没有太多智慧的最佳实践。好奇我是否应该将我的 do_things 函数更改为 Python class 并使用一个名为 do_things 的方法,然后这个 class 可以从 Javascript 调用?

.js

const { PythonShell } = require("python-shell");
let pyshell = new PythonShell("my_script.py");
pyshell.send("hello");
pyshell.on("message", function (message) {
  console.log(message);
});
setTimeout(() => {
  pyshell.send("Another Hello");
}, 3000);
const end = () => {
  pyshell.end(function (err, code, signal) {
    if (err) throw err;
    console.log("finished");
  });
};
// end();

.py

import sys
    
def log():  
    print('hello from python')
while True:
    inp = input(" ")
    if inp=="hello":
        log()

这将保留进程 运行 除非您从 nodejs 调用 end 方法或发生某些错误。这可能会导致性能问题,因为 python thingy 将与您的 nodejs 共享相同的资源。更好的方法是使用微服务,例如部署一些处理 python 特定任务的 Rest Api。

只是为了好玩 post 我从@sandeep 那里学到的东西(感谢一百万 btw),这很有效。我可以在 60 秒 setInterval(pythonDo, 60000); 上打印从 Python 从 运行 一个 javascript 文件收集的 BACnet 传感器值,同时保持 Python 文件处于活动状态:

C:\Program Files\nodejs\node.exe .\start.js
BAC0 start success
 68.47
 68.43
 68.29
 68.25

start.js

const { PythonShell } = require("python-shell");

let pyshell = new PythonShell("bac0Worker.py");

function pythonDo() {
  pyshell.send("read 12345:2 analogInput 2"); 
}

pyshell.on("message", function (message) {
  console.log(message);
});

var data = setInterval(pythonDo, 60000);

bac0Worker.py

import sys
import BAC0

BAC0.log_level('silence')
bacnet = BAC0.lite()
print("BAC0 start success")

# available BACnet actions
SUBSTRING_READ = "read"
SUBSTRING_WRITE = "write"
SUBSTRING_RELEASE = "release"


def bac0_worker(action, BACnet_request, **kwargs):
    value = kwargs.get('value', None)
    priority = kwargs.get('priority', None)

    if action == "read":
        try:
            read_vals = f'{BACnet_request} presentValue'
            read_result = bacnet.read(read_vals)
            if isinstance(read_result, str):
                pass
            else:
                read_result = round(read_result,2)
            print(read_result)
        except Exception as error:
            print("read error")
  
    elif action == "write":
        try:
            write_vals = f'{BACnet_request} presentValue {value} - {priority}'
            bacnet.write(write_vals)
            print(write_vals)         
        except Exception as error:
            print("write error")

    elif action == "release":
        try:    
            release_vals = f'{BACnet_request} presentValue null - {priority}'
            bacnet.write(release_vals)
            print(release_vals)
        except Exception as error:
            print("release error")
    else:
        return "server error on BACnet opts"


def main():
        while True:
            # from javascript
            inp = input(" ")

            for word in inp.split():
                if SUBSTRING_READ == word:
                    stripped_string = inp.replace(SUBSTRING_READ + " ", "")
                    # do a BACnet READ request with BAC0
                    bac0_worker(SUBSTRING_READ,stripped_string)

                if SUBSTRING_WRITE == word:
                    print("WRITE Match Found")

                if SUBSTRING_RELEASE == word:
                    print("RELEASE Match Found")                    



if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("bacnet app error")
        bacnet.disconnect()