UNPKG

wsemi

Version:

A support package for web developer.

288 lines (231 loc) 6.43 kB
import get from 'lodash-es/get.js' import each from 'lodash-es/each.js' import isarr from './isarr.mjs' import loadPyodide from './_loadPyodide.js' import getGlobal from './getGlobal.mjs' import haskey from './haskey.mjs' import waitFun from './waitFun.mjs' import queue from './queue.mjs' // console.log('loadPyodide', loadPyodide) //pyodide於VM上之node下執行有問題,主要是請求request無法設定head,待日後確認是否有新版並修復 function getLoadPyodide() { let g = getGlobal() let x = loadPyodide || g.loadPyodide // console.log('getLoadPyodide loadPyodide', x) return x } let state = '' let pyodide = null let micropip = null async function iniPyodide() { //state if (state === 'done') { return } else if (state === 'loading') { await waitFun(() => { return pyodide !== null }) return } state = 'loading' //getLoadPyodide let lpd = getLoadPyodide() // console.log('lpd', lpd) //lpd let _pyodide = await lpd() // console.log('_pyodide',_pyodide) await _pyodide.loadPackage('micropip') let _micropip = _pyodide.pyimport('micropip') // console.log('_micropip',_micropip) //save pyodide = _pyodide micropip = _micropip //state state = 'done' } let q = null let kp = {} if (true) { //queue let takeLimit = 1 q = queue(takeLimit) //message q.on('message', function(qs) { // console.log('message', JSON.stringify(qs)) //get let pkg = q.get() if (!pkg) { return } // console.log('get', pkg) async function core() { //loading if (!haskey(kp, pkg)) { kp[pkg] = 'loading' } //install and loadPackage await micropip.install(pkg) await pyodide.loadPackage(pkg) // console.log('inst-load pkg',pkg) //done kp[pkg] = 'done' //cb q.cb() // console.log('finish',pkg) } core() .catch((err) => { console.log(err) }) }) } function loadPkg(pkg) { q.push(pkg) } async function checkPkgs(pkgs) { await waitFun(() => { // console.log('check pkgs',pkgs) let b = true each(pkgs, (pkg) => { let c = get(kp, pkg) if (c !== 'done') { b = false return false //跳出 } }) return b }) } async function loadPkgs(pkgs) { //loadPkg each(pkgs, (pkg) => { loadPkg(pkg) }) //checkPkgs await checkPkgs(pkgs) } /** * 通過Pyodide執行Python程式碼 * * Unit Test: {@link https://github.com/yuda-lyu/wsemi/blob/master/test/execPyodide.test.mjs Github} * @memberOf wsemi * @param {Object} [opt={}] 輸入設定物件,預設{} * @param {Array} [opt.pkgs=[]] 輸入Python引用已安裝套件字串陣列,例如為'scipy'、'numpy'等,預設[] * @param {Array} [opt.imps=[]] 輸入Python引入(import)的字串陣列,例如為['import scipy','import numpy']等,預設[] * @param {Array} [opt.inps=[]] 輸入輸入數據陣列,例如為[123,'abc']等,預設[] * @param {String} [opt.content=''] 輸入執行程式核心字串,若要使用inps則使用'rIn數字',數字由1至inps的長度n,回傳使用'ret'接收,例如ret = fun(rIn1,rIn2,...rInn),預設'' * @returns {Number|String|Boolean|Array|Object} 回傳運算結果資料 * @example * * async function test() { * * let pkgs = [ * 'scipy', * ] * let imps = [ * 'from scipy.interpolate import griddata', * ] * let psSrc = [ * [-0.1, -0.1, -0.1, 0], * [1, 0, 0, 0], * [1, 1, 0, 0], * [0, 0, 1, 0], * [1, 0, 1, 0], * [1, 1, 1, 10], * ] * let psLocs = [] * let psValus = [] * for (let k = 0; k < psSrc.length; k++) { * let v = psSrc[k] * psLocs.push([v[0], v[1], v[2]]) * psValus.push(v[3]) * } * let psTar = [ * 0.1, 0.1, 0.95 * ] * let inps = [ * psLocs, * psValus, * psTar, * ] * let content = ` * ret = griddata(rIn1, rIn2, rIn3, method='linear') * ` * let rs = await execPyodide({ * pkgs, * imps, * inps, * content, * }) * console.log('rs', rs) * * } * * test() * .catch((err) => { * console.log(err) * }) * // Loading micropip, packaging * // Loaded packaging, micropip * // Loading scipy, numpy, clapack * // Loaded clapack, numpy, scipy * // scipy already loaded from default channel * // No new packages to load * // rs Float64Array(1) [ 0.49999999999999933 ] * */ async function execPyodide(opt = {}) { //pkgs let pkgs = get(opt, 'pkgs', []) if (!isarr(pkgs)) { pkgs = [] } //imps let imps = get(opt, 'imps', []) if (!isarr(imps)) { imps = [] } //inps let inps = get(opt, 'inps', []) if (!isarr(inps)) { inps = [] } //content, 執行Python程式碼, 例如 ret = griddata(rIn1, rIn2, rIn3, method='linear') let content = get(opt, 'content', '') //iniPyodide await iniPyodide() //loadPkgs await loadPkgs(pkgs) //cimps let cimps = '' each(imps, (imp) => { cimps += imp + '\n' }) // console.log('cimps', cimps) //cins, 待之後與pyodide.globals.set變數提高效能, 可能有轉型問題, 待確認 let cins = '' each(inps, (v, k) => { cins += `rIn${k + 1} = ${JSON.stringify(v)}` + '\n' }) // console.log('cins', cins) //scp let scp = ` ${cimps} ${cins} ret = '' ${content} # print(ret) ` //runPython await pyodide.runPython(scp) //r let r = pyodide.globals.get('ret').toJs() // console.log('r', r) // //cdbl // rs = map(rs, (v) => { // return cdbl(v) // }) return r } export default execPyodide