使用Js2Py在Python中嵌入JavaScript时Pylance报错求助
问题描述
我尝试在Python应用中使用Js2Py库嵌入JavaScript代码,但Pylance持续抛出错误:第34行提示“{未闭合”(实际已正确闭合),第35行的“global”处提示“expected expression”。请问我存在哪些操作错误或遗漏点?
import js2py # var_stars = js2py.eval_var('var') var_stars = [ [0, 1.39734], [2.6521683, 0], [2.5652089, 5.97229], [5.6232309, 2.98584], [2.1902414, 2.23642] ] # const = js2py.eval_const('const') # A4 = js2py.eval_A4('A4') # A4Width = js2py.eval_A4Width('A4Width') const_A4Width = 210 const_A4Height = 297 A4_measures = const_A4Width * const_A4Height const_A4Margin = 5 setTimeout = js2py.eval_setTimeout('setTimeout') document = js2py.eval_document('document') generatePDF = js2py.eval_generatePDF('generatePDF') # const = js2py.eval_const('const') # console = js2py.eval_console('console') def generatePDF(): { global jsPDF var doc = new jsPDF(); const color = document.querySelector('select').value; console.log(color); doc.setFillColor(255, 255, 255); doc.setLineWidth(1); doc.setDrawColor(0,255,0); doc.circle(120, 20, 5, "S"); var points = generatePoints(200, 10, A4Margin, A4Width-A4Margin-6, A4Margin, A4Height-A4Margin-6); for( var i=0; i<points.length; i++ ) { drawEurion(points[i][0], points[i][1], Math.random()*2*Math.PI, color); } for( var i=0; i<points.length; i++ ) { console.log(points[i][0], points[i][1]) for( var j=i+1; j<points.length; j++ ) { var distance = Math.sqrt(Math.pow(points[i][0]-points[j][0],2)+Math.pow(points[i][1]-points[j][1],2)) if( distance<10 ) console.log('d', i, j, Math.sqrt(Math.pow(points[i][0]-points[j][0],2)+Math.pow(points[i][1]-points[j][1],2)) ) } } //doc.save("eurion.pdf") //pdf_test_harness_init(pdf, "Open in Reader (or Firefox) to see the PDF outline"); //doc.output('datauri') //datauri document.querySelector('iframe').src=doc.output('datauristring'); function drawEurion(offsetX, offsetY, angle, color) { doc.setDrawColor(color); doc.setLineWidth(0.24834293); const centreX = 2.6; const centreY = 3; for( var i=0; i<stars.length; i++ ) { var x = offsetX + centreX + Math.cos(angle)*(stars[i][0]-centreX) + Math.sin(angle)*(stars[i][1]-centreY) var y = offsetY + centreY - Math.sin(angle)*(stars[i][0]-centreX) + Math.cos(angle)*(stars[i][1]-centreY) doc.circle(x, y, 0.36089846, "S"); } //doc.setDrawColor(0,255,0); //doc.circle(offsetX+centreX, offsetY+centreY, 4.4, "S"); } function generatePoints(number, distance, minX, maxX, minY, maxY, ) { var points = []; var tries = 0; while( points.length<number && tries<40 ) { tries = 0; var validPoint = false; while( tries<40 && validPoint==false ) { tries++; var x = minX + Math.random()*(maxX-minX) var y = minY + Math.random()*(maxY-minY) validPoint = true for( var i=0; i<points.length; i++ ) { if( Math.sqrt(Math.pow(points[i][0]-x,2)+Math.pow(points[i][1]-y,2))<distance ) //if( Math.abs(points[i][0]-x)<distance/2 || Math.abs(points[i][1]-y)<distance/2 ) { validPoint = false; break; } } if( validPoint ) points.push([x,y]) } } return points } setTimeout(generatePDF, 10) document.querySelector('select').oninput = generatePDF(); document.querySelector('select').onchange = generatePDF(); document.querySelector('form').onsubmit = (setTimeout(generatePDF()), 10) return False }
错误分析
你的代码存在以下核心问题:
- 语法混淆:把JavaScript语法直接写在Python函数中,Pylance会按照Python语法规则解析代码:
- Python函数体不需要用
{}包裹,而是靠缩进区分代码块,你写的{会被Python解析器视为语法错误。 var、const、function是JavaScript关键字,不是Python语法,Pylance会报错“expected expression”。- Python的
global关键字用于声明Python全局变量,但你用它来标记JS的jsPDF,完全不符合Python语法逻辑。
- Python函数体不需要用
- Js2Py使用方式错误:Js2Py的核心是将JS代码作为字符串传入
js2py.eval_js()或js2py.compile_js()执行,而不是直接把JS代码混在Python函数里。你尝试的js2py.eval_setTimeout这类写法不存在,Js2Py会自动模拟JS全局环境,直接在JS代码中使用setTimeout、console即可。 - 变量作用域错误:Python中的
var_stars、const_A4Width等变量无法直接在JS代码中使用,需要手动注入到JS环境。 - Python缩进错误:代码中
var_stars、const_A4Width等变量的缩进层级不对,不符合Python的缩进规范。
修正方案
将JavaScript代码抽离为单独的字符串,使用Js2Py执行并注入所需的Python变量,同时修正Python语法问题:
import js2py # Python端定义的变量 var_stars = [ [0, 1.39734], [2.6521683, 0], [2.5652089, 5.97229], [5.6232309, 2.98584], [2.1902414, 2.23642] ] const_A4Width = 210 const_A4Height = 297 const_A4Margin = 5 # 定义JavaScript代码字符串 js_code = """ function generatePDF() { var doc = new jsPDF(); // 注意:这里的document是JS环境模拟对象,实际使用时可能需要替换为对应的模拟实现 const color = document.querySelector('select').value; console.log(color); doc.setFillColor(255, 255, 255); doc.setLineWidth(1); doc.setDrawColor(0,255,0); doc.circle(120, 20, 5, "S"); var points = generatePoints(200, 10, A4Margin, A4Width-A4Margin-6, A4Margin, A4Height-A4Margin-6); for( var i=0; i<points.length; i++ ) { drawEurion(points[i][0], points[i][1], Math.random()*2*Math.PI, color); } for( var i=0; i<points.length; i++ ) { console.log(points[i][0], points[i][1]); for( var j=i+1; j<points.length; j++ ) { var distance = Math.sqrt(Math.pow(points[i][0]-points[j][0],2)+Math.pow(points[i][1]-points[j][1],2)); if( distance<10 ) { console.log('d', i, j, distance); } } } document.querySelector('iframe').src=doc.output('datauristring'); function drawEurion(offsetX, offsetY, angle, color) { doc.setDrawColor(color); doc.setLineWidth(0.24834293); const centreX = 2.6; const centreY = 3; for( var i=0; i<stars.length; i++ ) { var x = offsetX + centreX + Math.cos(angle)*(stars[i][0]-centreX) + Math.sin(angle)*(stars[i][1]-centreY); var y = offsetY + centreY - Math.sin(angle)*(stars[i][0]-centreX) + Math.cos(angle)*(stars[i][1]-centreY); doc.circle(x, y, 0.36089846, "S"); } } function generatePoints(number, distance, minX, maxX, minY, maxY) { var points = []; var tries = 0; while( points.length<number && tries<40 ) { tries = 0; var validPoint = false; while( tries<40 && validPoint==false ) { tries++; var x = minX + Math.random()*(maxX-minX); var y = minY + Math.random()*(maxY-minY); validPoint = true; for( var i=0; i<points.length; i++ ) { if( Math.sqrt(Math.pow(points[i][0]-x,2)+Math.pow(points[i][1]-y,2))<distance ) { validPoint = false; break; } } if( validPoint ) { points.push([x,y]); } } } return points; } setTimeout(generatePDF, 10); document.querySelector('select').oninput = generatePDF; document.querySelector('select').onchange = generatePDF; document.querySelector('form').onsubmit = function() { setTimeout(generatePDF, 10); return false; }; } // 执行生成PDF函数 generatePDF(); """ # 创建JS上下文,注入Python变量 context = js2py.EvalJs() context.stars = var_stars context.A4Width = const_A4Width context.A4Height = const_A4Height context.A4Margin = const_A4Margin # 注意:jsPDF需要提前在JS环境中加载,你可以通过context.eval_js()加载jsPDF的CDN代码 # 例如:context.eval_js(""" # var script = document.createElement('script'); # script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js'; # document.head.appendChild(script); # """) # 执行JS代码 context.eval_js(js_code)
额外说明
- 如果你需要模拟
document、window等浏览器环境,Js2Py默认的环境不包含这些对象,需要自己实现或使用额外的模拟逻辑。 jsPDF需要在JS环境中提前加载,你可以通过注入脚本的方式引入其资源。- 修正了JS代码中的语法细节(如多余的逗号、缺少的分号),避免JS执行时出错。
内容的提问来源于stack exchange,提问作者Squirtgun187
相关产品推荐
相关产品推荐

