TypeError: PythonShell is not a constructor
TypeError: PythonShell is not a constructor
我正在试验 node red - VOLTTRON(Python 框架)integration 我希望在 Node Red 中查看 VOLTTRON 消息总线。
当我执行 README 中定义的适当步骤时,例如将文件复制到正确的 ~/.node-red/nodes/volttron
并获取正确的 VOLTTRON 身份验证密钥
当我启动 Node Red 时,出现错误:
12 Dec 14:07:54 - [info] Server now running at http://127.0.0.1:8000/
12 Dec 14:07:54 - [info] Starting flows
12 Dec 14:07:54 - [info] Started flows
12 Dec 14:07:54 - [warn] [volttron-input:03074cce8abc3174] /home/ben/.node-red/nodes/volttron
12 Dec 14:07:54 - [warn] [volttron-input:03074cce8abc3174] /home/ben/.node-red/nodes/volttron/node_red_subscriber.py
12 Dec 14:07:54 - [red] Uncaught Exception:
12 Dec 14:07:54 - TypeError: PythonShell is not a constructor
at Timeout._onTimeout (/home/ben/.node-red/nodes/volttron/volttron.js:33:23)
at listOnTimeout (internal/timers.js:554:17)
at processTimers (internal/timers.js:497:7)
我不确定这是否是与 javascript 或 Python 相关的问题?感谢您提供零智慧旁边的任何提示。
volttron.js
module.exports = function(RED) {
// Set these variables to be valid file paths
var volttron_env = '/home/ben/.volttron';
var volttron_home = '/home/ben/Desktop/volttron';
var python_path = '/usr/lib/python3.8';
function VolttronInputNode(config) {
RED.nodes.createNode(this,config);
var node = this;
var pyshell = null;
this.on('close', function(done) {
setTimeout(function() {
/* do some asynchronous cleanup before calling done */
if (pyshell && !pyshell.terminated && pyshell.childProcess)
pyshell.childProcess.kill('SIGINT');
done();
});
});
setTimeout(function() {
var PythonShell = require('python-shell');
process.env['VIRTUAL_ENV'] = volttron_env;
process.env['VOLTTRON_HOME'] = volttron_home;
var options = {
mode: 'json',
pythonPath: python_path,
scriptPath: __dirname,
};
var path = require('path');
node.warn(__dirname);
var scriptName = 'node_red_subscriber.py';
var scriptPath = path.resolve(__dirname, scriptName);
node.warn(scriptPath);
pyshell = new PythonShell(scriptName, options);
pyshell.on('message', function (data) {
msg = {};
msg.topic = node.name;
msg.payload = data;
node.send(msg);
});
pyshell.end(function (err) {
node.error(err);
});
});
}
RED.nodes.registerType("volttron-input", VolttronInputNode);
function VolttronOutputNode(config) {
RED.nodes.createNode(this,config);
var node = this;
this.on('close', function(done) {
setTimeout(function() { /* do some asynchronous cleanup before calling done */ done(); });
});
this.on("input", function (msg) {
setTimeout(function() { // send asynchronously
var PythonShell = require('python-shell');
process.env['VIRTUAL_ENV'] = volttron_env;
process.env['VOLTTRON_HOME'] = volttron_home;
var options = {
mode: 'json',
pythonPath: python_path,
scriptPath: __dirname,
args: [msg.payload.topic, msg.payload.data]
};
var path = require('path');
var scriptName = 'node_red_publisher.py';
var scriptPath = path.resolve(__dirname, scriptName);
PythonShell.run(scriptName, options, function(err, result) {
if (err) node.error(err);
if (result) node.warn(result);
});
});
});
}
RED.nodes.registerType("volttron-output",VolttronOutputNode);
}
node_red_subscriber.py
from datetime import datetime
import os
import sys
import gevent
from volttron.platform.messaging import headers as headers_mod
from volttron.platform.vip.agent import Agent, PubSub, Core
from volttron.platform.agent import utils
from volttron.platform.scheduling import periodic
from volttron.platform import jsonapi
from settings import topic_prefixes_to_watch, heartbeat_period, agent_kwargs
class NodeRedSubscriber(Agent):
def onmessage(self, peer, sender, bus, topic, headers, message):
d = {'topic': topic,
'headers': headers,
'message': message}
sys.stdout.write(jsonapi.dumps(d)+'\n')
sys.stdout.flush()
@Core.receiver('onstart')
def onstart(self, sender, **kwargs):
for prefix in topic_prefixes_to_watch:
self.vip.pubsub.subscribe(peer='pubsub', prefix=prefix, callback=self.onmessage).get(timeout=10)
# Demonstrate periodic decorator and settings access
@Core.schedule(periodic(heartbeat_period))
def publish_heartbeat(self):
now = utils.format_timestamp(datetime.utcnow())
headers = {
headers_mod.CONTENT_TYPE: headers_mod.CONTENT_TYPE.PLAIN_TEXT,
headers_mod.DATE: now,
headers_mod.TIMESTAMP: now
}
result = self.vip.pubsub.publish('pubsub', 'heartbeat/NodeRedSubscriber', headers, now)
result.get(timeout=10)
if __name__ == '__main__':
try:
# If stdout is a pipe, re-open it line buffered
if utils.isapipe(sys.stdout):
# Hold a reference to the previous file object so it doesn't
# get garbage collected and close the underlying descriptor.
stdout = sys.stdout
sys.stdout = os.fdopen(stdout.fileno(), 'w', 1)
agent = NodeRedSubscriber(identity='NodeRedSubscriber', **agent_kwargs)
task = gevent.spawn(agent.core.run)
try:
task.join()
finally:
task.kill()
except KeyboardInterrupt:
pass
编辑
进一步尝试一些步骤,在目录 .node-red/node_modules
中,我放置了一个名为 package.json
的文件,其中包含答案中提供的内容以及答案中提供的依赖项 "python-shell": "^1.0.4"
。然后从 bash 的同一目录 运行 出现一些 npm 错误:
~/.node-red/node_modules$ npm install volttron
回溯:
npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/volttron - Not found
npm ERR! 404
npm ERR! 404 'volttron@*' is not in this registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
npm ERR! A complete log of this run can be found in:
npm ERR! /home/ben/.npm/_logs/2021-12-13T12_52_57_550Z-debug.log
在其他目录中~/.node-red/nodes/volttron
存在这些文件:
node_red_publisher.py node_red_subscriber.py README settings.py volttron.html volttron.js
在之前的中,我不得不猜测节点使用的是哪个版本的python-shell
,因为它没有任何提示,所以我选择了当前的最新版本(3.0.1)作为任意选择。
看来这是错误的选择,所以我建议您再次编辑 package.json
文件并将 python-shell
依赖项的 ^3.0.1
版本更改为 ^1.0.4
{
"name" : "volttron",
"version" : "0.0.1",
"description" : "A sample node for node-red",
"dependencies": {
"python-shell": "^1.0.4"
},
"keywords": [ "node-red" ],
"node-red" : {
"nodes": {
"volttron": "volttron.js"
}
}
}
您需要在 volttron
目录中进行更改后再次 运行 npm install
。
如果不是这种情况,那么您将不得不与 Volttron 联系。
我正在试验 node red - VOLTTRON(Python 框架)integration 我希望在 Node Red 中查看 VOLTTRON 消息总线。
当我执行 README 中定义的适当步骤时,例如将文件复制到正确的 ~/.node-red/nodes/volttron
并获取正确的 VOLTTRON 身份验证密钥
当我启动 Node Red 时,出现错误:
12 Dec 14:07:54 - [info] Server now running at http://127.0.0.1:8000/
12 Dec 14:07:54 - [info] Starting flows
12 Dec 14:07:54 - [info] Started flows
12 Dec 14:07:54 - [warn] [volttron-input:03074cce8abc3174] /home/ben/.node-red/nodes/volttron
12 Dec 14:07:54 - [warn] [volttron-input:03074cce8abc3174] /home/ben/.node-red/nodes/volttron/node_red_subscriber.py
12 Dec 14:07:54 - [red] Uncaught Exception:
12 Dec 14:07:54 - TypeError: PythonShell is not a constructor
at Timeout._onTimeout (/home/ben/.node-red/nodes/volttron/volttron.js:33:23)
at listOnTimeout (internal/timers.js:554:17)
at processTimers (internal/timers.js:497:7)
我不确定这是否是与 javascript 或 Python 相关的问题?感谢您提供零智慧旁边的任何提示。
volttron.js
module.exports = function(RED) {
// Set these variables to be valid file paths
var volttron_env = '/home/ben/.volttron';
var volttron_home = '/home/ben/Desktop/volttron';
var python_path = '/usr/lib/python3.8';
function VolttronInputNode(config) {
RED.nodes.createNode(this,config);
var node = this;
var pyshell = null;
this.on('close', function(done) {
setTimeout(function() {
/* do some asynchronous cleanup before calling done */
if (pyshell && !pyshell.terminated && pyshell.childProcess)
pyshell.childProcess.kill('SIGINT');
done();
});
});
setTimeout(function() {
var PythonShell = require('python-shell');
process.env['VIRTUAL_ENV'] = volttron_env;
process.env['VOLTTRON_HOME'] = volttron_home;
var options = {
mode: 'json',
pythonPath: python_path,
scriptPath: __dirname,
};
var path = require('path');
node.warn(__dirname);
var scriptName = 'node_red_subscriber.py';
var scriptPath = path.resolve(__dirname, scriptName);
node.warn(scriptPath);
pyshell = new PythonShell(scriptName, options);
pyshell.on('message', function (data) {
msg = {};
msg.topic = node.name;
msg.payload = data;
node.send(msg);
});
pyshell.end(function (err) {
node.error(err);
});
});
}
RED.nodes.registerType("volttron-input", VolttronInputNode);
function VolttronOutputNode(config) {
RED.nodes.createNode(this,config);
var node = this;
this.on('close', function(done) {
setTimeout(function() { /* do some asynchronous cleanup before calling done */ done(); });
});
this.on("input", function (msg) {
setTimeout(function() { // send asynchronously
var PythonShell = require('python-shell');
process.env['VIRTUAL_ENV'] = volttron_env;
process.env['VOLTTRON_HOME'] = volttron_home;
var options = {
mode: 'json',
pythonPath: python_path,
scriptPath: __dirname,
args: [msg.payload.topic, msg.payload.data]
};
var path = require('path');
var scriptName = 'node_red_publisher.py';
var scriptPath = path.resolve(__dirname, scriptName);
PythonShell.run(scriptName, options, function(err, result) {
if (err) node.error(err);
if (result) node.warn(result);
});
});
});
}
RED.nodes.registerType("volttron-output",VolttronOutputNode);
}
node_red_subscriber.py
from datetime import datetime
import os
import sys
import gevent
from volttron.platform.messaging import headers as headers_mod
from volttron.platform.vip.agent import Agent, PubSub, Core
from volttron.platform.agent import utils
from volttron.platform.scheduling import periodic
from volttron.platform import jsonapi
from settings import topic_prefixes_to_watch, heartbeat_period, agent_kwargs
class NodeRedSubscriber(Agent):
def onmessage(self, peer, sender, bus, topic, headers, message):
d = {'topic': topic,
'headers': headers,
'message': message}
sys.stdout.write(jsonapi.dumps(d)+'\n')
sys.stdout.flush()
@Core.receiver('onstart')
def onstart(self, sender, **kwargs):
for prefix in topic_prefixes_to_watch:
self.vip.pubsub.subscribe(peer='pubsub', prefix=prefix, callback=self.onmessage).get(timeout=10)
# Demonstrate periodic decorator and settings access
@Core.schedule(periodic(heartbeat_period))
def publish_heartbeat(self):
now = utils.format_timestamp(datetime.utcnow())
headers = {
headers_mod.CONTENT_TYPE: headers_mod.CONTENT_TYPE.PLAIN_TEXT,
headers_mod.DATE: now,
headers_mod.TIMESTAMP: now
}
result = self.vip.pubsub.publish('pubsub', 'heartbeat/NodeRedSubscriber', headers, now)
result.get(timeout=10)
if __name__ == '__main__':
try:
# If stdout is a pipe, re-open it line buffered
if utils.isapipe(sys.stdout):
# Hold a reference to the previous file object so it doesn't
# get garbage collected and close the underlying descriptor.
stdout = sys.stdout
sys.stdout = os.fdopen(stdout.fileno(), 'w', 1)
agent = NodeRedSubscriber(identity='NodeRedSubscriber', **agent_kwargs)
task = gevent.spawn(agent.core.run)
try:
task.join()
finally:
task.kill()
except KeyboardInterrupt:
pass
编辑
进一步尝试一些步骤,在目录 .node-red/node_modules
中,我放置了一个名为 package.json
的文件,其中包含答案中提供的内容以及答案中提供的依赖项 "python-shell": "^1.0.4"
。然后从 bash 的同一目录 运行 出现一些 npm 错误:
~/.node-red/node_modules$ npm install volttron
回溯:
npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/volttron - Not found
npm ERR! 404
npm ERR! 404 'volttron@*' is not in this registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
npm ERR! A complete log of this run can be found in:
npm ERR! /home/ben/.npm/_logs/2021-12-13T12_52_57_550Z-debug.log
在其他目录中~/.node-red/nodes/volttron
存在这些文件:
node_red_publisher.py node_red_subscriber.py README settings.py volttron.html volttron.js
在之前的python-shell
,因为它没有任何提示,所以我选择了当前的最新版本(3.0.1)作为任意选择。
看来这是错误的选择,所以我建议您再次编辑 package.json
文件并将 python-shell
依赖项的 ^3.0.1
版本更改为 ^1.0.4
{
"name" : "volttron",
"version" : "0.0.1",
"description" : "A sample node for node-red",
"dependencies": {
"python-shell": "^1.0.4"
},
"keywords": [ "node-red" ],
"node-red" : {
"nodes": {
"volttron": "volttron.js"
}
}
}
您需要在 volttron
目录中进行更改后再次 运行 npm install
。
如果不是这种情况,那么您将不得不与 Volttron 联系。