【问题标题】:python-shell node, keep a python script runningpython-shell节点,保持python脚本运行
【发布时间】:2021-12-28 20:01:13
【问题描述】:

有谁知道在使用 python-shell 时是否可以在从 Javascript 调用 python 脚本时保持运行?也许使用 python-shell 从 Javascript 调用 Python 类中的方法?

例如,这段代码可以工作,但每次调用它都会杀死 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 脚本运行,我认为在 BAC0 的引擎盖下有很多过程正在进行,如果脚本启动/停止,它可能会在 BACnet 网络上产生大量不必要的流量很多。

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 脚本运行有任何提示,然后我可以将值(传感器和设备寻址信息)传递给 BAC0 脚本以请求 BACnet从网络读取。在 Python 文件的 main 函数中,如果我替换这个:

# all done    
bacnet.disconnect()

与:

while True:
    pass

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

【问题讨论】:

    标签: python node.js stdout stdin


    【解决方案1】:

    .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。

    【讨论】:

    • setTimeout(() => { pyshell.send("Another Hello"); }, 10); 是做什么的?
    • 在这里感谢您的帮助.....
    • 你能再给我一个提示吗?如何定期修改pyshell.send("Another Hello");?例如每 60 秒 pyshell.send("Another Hello");
    • setTimeout(() => { pyshell.send("Another Hello"); }, timeInMilliSeconds); 仅用于演示目的...如果您想连续运行某些东西,请将setTimeout 替换为setInterval。更多关于 setInterval 的信息:developer.mozilla.org/en-US/docs/Web/API/setInterval
    • 基本语法是setInterval( functionYouWantToRun , timeInMilliseconds )
    【解决方案2】:

    只是为了好玩我会发布我从@sandeep 学到的东西(谢谢一百万顺便说一句),这很有效。我可以打印从 Python 收集的 BACnet 传感器值,这些值是通过在 60 秒 setInterval(pythonDo, 60000); 上运行 javascript 文件并保持 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()
    

    【讨论】:

    • 有趣的工作人员 henry,@sandeep.kgp
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 2013-07-27
    • 1970-01-01
    • 2020-01-01
    • 1970-01-01
    相关资源
    最近更新 更多