首页 > 解决方案 > 如何使用python shell将长度超过4000的参数从Javascript传递到Python

问题描述

我正在使用 node.js、electron.js、Vue.js 和 Python 构建一个桌面应用程序。我正在使用 python 进行一些打印。我正在使用 python-shell npm 库(https://www.npmjs.com/package/python-shell)。在 python 中,我使用 pywin32 和 sys 库来打印并获取我从 JavaScript 代码传递的参数。在我的 JavaScript 代码中,我完成了如下操作,我的输出有 4000 多个字符。这是我想要打印的字符串。但并非所有的行都被打印出来。传递值时是否有字符限制?如果是这样,我怎么知道限制,有人可以建议我更好的方法来做到这一点

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

var options = {          
        pythonOptions: ['-u'],
        scriptPath: __dirname,
        args: [printerName, output, imgPath]
};

PythonShell.run("../../../../extras/script/printer.py", options, function (err, results) {
    if (err) throw err;
    for(var k in results){
        console.log(results[k])
    }              
});

标签: javascriptpython

解决方案


命令行有一个最大大小,这取决于您的操作系统(也可能是您的设置)。1该命令行必须足以容纳 Python 解释器的名称、您的脚本路径、以及您的-u所有(正确引用的)args。你的系统上可能是 4096,所以当你有大约 4000 个字符的参数时,事情就开始失败了。

对此有两种通用解决方案。


首先,如果脚本通过循环使用参数并独立处理它们,就像许多 Unix 工具所做的那样,您可以一次使用 50 个参数重复调用它。这基本上与xargs用于大型参数列表的技巧相同。


其次,您可以更改脚本以从文件或标准输入中读取其输入,而不是从命令行参数中读取。

您还没有向我们展示您的代码,但假设它看起来像这样:

import sys
for arg in sys.argv[1:]:
    print('arg:', arg)

你可以把它改成这样:

import sys
for line in sys.stdin:
    print('arg:', line, end='')

但是现在你必须改变调用方。我不知道 PythonShell,而且我的 JS 很生疏,但是快速浏览一下文档示例,它看起来应该是这样的:

var options = {          
        pythonOptions: ['-u'],
        scriptPath: 'myscript.py',
};

myscript = new PythonShell(options);
var results = [];
myscript.on('message', function(message)) {
    results += [message];
}
for (var i in args) {
    myscript.send(args[i] + '\n');
}
myscript.end(function(err, code, signal) {    
    if (err) throw err;
    for (var k in results){
        console.log(results[k])
    }              
});

使用文件而不是标准输入非常相似。它看起来像这样:

import sys
filename = sys.argv[1]
with open(filename) as f:
    for line in f:
        print('arg:', line, end='')

然后调用它更接近您的原始代码:

tempFile = new IDontRememberHowToSecurelyMakeATempFileInNode();
for (var i in args) {
    tempFile.write(args[i] + '\n');
}

var options = {          
    pythonOptions: ['-u'],
    scriptPath: __dirname,
    args: [tempFile.howeverYouGetTheFileName()]
};

PythonShell.run("../../../../extras/script/printer.py", options, function (err, results) {
    if (err) throw err;
    for(var k in results){
        console.log(results[k])
    }              
});

1. 在 Windows 上,比这更复杂。在某些版本中,命令行参数和环境变量集必须在另一个限制之下,并且 UTF-16 与 8 位输入的限制可能不同,如果您使用的是MSVCRT 函数模拟 POSIX 风格的 API,而不是直接调用 Windows API 等。


推荐阅读