簡體   English   中英

python-shell節點,保持python腳本運行

[英]python-shell node, keep a python script running

如果您可以在從 Javascript 調用 python 腳本時保持運行,那么有人會知道使用 python-shell 嗎? 也許使用 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 的 package。 我想要做的是弄清楚我是否可以保持 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 腳本以請求從網絡。 如果我替換此文件,則在 Python 文件的主 function 中:

# all done    
bacnet.disconnect()

和:

while True:
    pass

這將使 Python 文件保持活動狀態我只是不知道如何使用 python-shell 將值傳遞給實時 Python 腳本。 感謝您提供的任何提示,而不是這里的最佳實踐。 Curious if I should change my do_things function into a Python class with a method called do_things where then this class could get called from 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 東西將與您的 nodejs 共享相同的資源。 更好的方法是使用微服務,例如部署一些 Rest Api 來處理 python 特定任務。

只是為了好玩我會發布我從@sandeep 學到的東西(謝謝一百萬順便說一句),這很有效。 我可以在 60 秒setInterval(pythonDo, 60000); 保持 Python 文件處於活動狀態:

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

開始.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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM