微信小程序可以用python 微信小程序可以用Python和java_python

1.前后端实现步骤:

1.前端采用的就是微信小程序开发工具,后端采用的是以springboot为基础,调用python中的Math类进行开发。
2.开发中遇到的难题不多
(1)小程序中主要就是光标的定位,如何在对应位置进行增删。
(2)后端遇到的问题,将 python 代码集成到 java 中,总体难度不大。(全网都是教程)
(3)在url中存在转义字符 如 ‘+’ 等问题处理方案。
(4) 发布到linux遇到的坑。理论上来讲,java调用的pythond 的包,不存在平台的适用性,但是作死的将python文件命名为中文,导致一直调用失败。

2.微信小程序 代码展示:

xxx.wxml

<view class="page">
  <view class="section">
    <textarea focus="true" auto-focus cursor="1" bindfocus="bindfocus" bindinput="bindinput2" data-set="{{textarea}}" style=" width:100%;background-color: #ddd;" value="{{textarea}}">{{textareaa}}</textarea>
    <!-- </view>  -->

    <view value="{{result}}">运行结果为:{{result}}</view>

    <!-- <textarea focus="true" auto-focus cursor="1" style="background-color: crimson;" bindinput="ceshi_textarea"  data-set="{{textarea}}"  value="{{textarea}}"></textarea> -->

    <!-- <view style="width: 100%;height:12%;background-color: #222;">
        <text style=" width:100%;height:5%;" value="{{result}}"></text>
      </view> -->
    <view class="view_1" style=" width:100%;background-color: #ddd;">
      <view >
        <button class="btn_1" bindtap="btn_zuo">←</button>
        <button class="btn_1" bindtap="btn_left">delete_left</button>
      </view>
      <view>
        <button class="btn_1" bindtap="btn_you">→</button>
        <button class="btn_1" bindtap="btn_clear">delete_all</button>
      </view>
    </view>

    <view class="tui-table-view">
      <view class='sort-ct-item' wx:for='{{list_1}}' wx:for-index="indexs" wx:for-item="items" wx:key="indexs">
        <view class="tui-col-1" data-set="{{items}}" bindtap="copyBtn">
          <view class='price'><text style="" data-set="{{items}}">{{items}}</text></view>
        </view>
      </view>
      <view style="width: 100%;"></view>
      <view class='sort-ct-item' wx:for='{{list_2}}' wx:for-index="indexs" wx:for-item="items" wx:key="indexs">
        <view class="tui-col-3" data-set="{{items}}" bindtap="copyBtn">
          <view class='price'><text style="border-radius: 5rpx;">{{items}}</text></view>
        </view>
      </view>
    </view>

    <button bindtap="btn_submit">提交</button>

  </view>
</view>

wxss.wxml

/* pages/kexuejisuanqi/kexuejisuanqi.wxss */
/* pages/科学计算器/科学计算器.wxss */
.page{
  width: 100%;
  height: 100%;
}
.section{
  position: fixed;
  bottom: 20rpx;
  background-color: burlywood;
}
.tui-table-view{
  display: -webkit-flex;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  width: 100%;
}
.tui-col-3{
 /* flex: 0 0 auto; */
  /* width: 19%; */
  text-align: center;
  color: #797979;
  padding: 15rpx ;
  margin-top: 10rpx;
  margin-bottom: 10rpx;
  font-size: 30rpx;
  border: 4rpx solid black;
}
.tui-col-1{
  /* flex: 0 0 auto; */
   /* width: 19%; */
   text-align: center;
   color: #797979;
   padding: 18rpx ;
   margin-top: 10rpx;
   margin-bottom: 10rpx;
   font-size: 40rpx;
   border: 4rpx solid black;
 }

.view_1{
  display: flex;
}

.btn_1{
  border-radius: 15rpx;
  padding: 10rpx 0;
  margin: 15rpx;
  font-family:'Courier New', Courier, monospace;
}

xxx.js

// pages/kexuejisuanqi/kexuejisuanqi.js
var app = getApp()
Page({

  /**
   * 页面的初始数据
   */
  data: {
    list_1: [
      '1', '2', '3', '4',
      '5', '6', '7', '8',
      '9', '0',
      '.', '+', '-', '*', '/',
      '(', ')'
    ],
    list_2: [
      // 绝对值
      'fabs',
      //阶乘 整数阶乘
      'factorial',
      //e 次 x 幂
      'exp',
      //返回 x 的自然对数(底为 e )
      'log',
      //将返回 x 的 y 次幂   两个参数
      'pow',
      //返回 x 的平方根。
      'sqrt',

      //三角函数         //返回以弧度为单位的 x 的反余弦值。 结果范围在 0 到 pi 之间。
      //返回以弧度为单位的 x 的反余弦值。 结果范围在 0 到 pi 之间。
      'acos',
      //返回以弧度为单位的 x 的反正弦值。 结果范围在 -pi/2 到 pi/2 之间。
      'asin',
      //返回以弧度为单位的 x 的反正切值。 结果范围在 -pi/2 到 pi/2 之间。
      'atan',
      //返回 x 弧度的余弦值。
      'sin',
      'cos',
      'tan',

      //角度弧度转换
      //将角度 x 从弧度转换为度数
      'degrees',
      //角度 x 从度数转换为弧度。
      'radians',

      //双曲函数
      //返回 x 的反双曲余弦值
      'acosh',
      //返回 x 的反双曲正弦值。
      'asinh',
      //返回 x 的反双曲正切值。
      'atanh',
      //返回 x 的双曲余弦值。
      'cosh',
      //返回 x 的双曲正弦值。
      'sinh',
      //返回 x 的双曲正切值。
      'tanh',
      //返回 x 处的 伽马函数 值。
      'gamma',
      // 返回Gamma函数在 x 绝对值的自然对数。
      'lgamma',

      //常量
      //pi
      'π',
      //e
      'e',
      //lgamma
      'lgamma',
    ],
    textarea: "",
    cursor: 0,
    guangbiao: false,
    guangbiaoqidong: false,
    result:''
  },

  btn_left:function(){
    console.log('btn_left')
    var textarea = this.data.textarea;
    var str = textarea.substring(0, this.data.cursor - 1)
    var str2 = textarea.substring(this.data.cursor)
    var str3 = str + str2;
    this.setData({
      textarea: str3,
      cursor: this.data.cursor - 1
    })
  },

  //固定位置插入| 光标
  btn_charu2: function () {
    var text = this.data.textarea;
    var t1 = this.data.textarea.substring(0, this.data.cursor);
    var t2 = this.data.textarea.substring(this.data.cursor)
    this.setData({
      textarea: t1 + "|" + t2,
      // cursor: this.data.cursor + 1
    })
  },
  //删除固定位置的光标 |
  btn_delete2: function () {
    var that = this
    for (var i = 0; i < that.data.textarea.length; i++) {
      // console.log(i)
      if (that.data.textarea.charAt(i) == '|') {
        that.data.textarea = that.data.textarea.replace('|', '')
      }
    }

  },
  //光标向左移动
  btn_zuo: function (e) {
    if (this.data.guangbiaoqidong == false) {
      this.data.guangbiaoqidong = true
      this.sendCode(e);
    }
    // this.hidden_view()
    console.log(this.data.cursor, this.data.textarea.charAt(this.data.cursor))
    this.setData({
      cursor: this.data.cursor - 1
    })
  },
  //光标向右移动
  btn_you: function (e) {
    if (this.data.guangbiaoqidong == false) {
      this.data.guangbiaoqidong = true
      this.sendCode(e);
    }
    console.log(this.data.cursor)
    this.setData({
      cursor: this.data.cursor + 1
    })
  },
  //光标 定时器
  sendCode: function (e) {
    var that = this;
    setInterval(function () {
      if (that.data.guangbiao == false) {
        // console.log('1')
        that.data.guangbiao = true
        that.btn_charu2()
      } else {
        // console.log('2')
        that.data.guangbiao = false
        that.btn_delete2()

      }
    }, 100)
  },
  //删除 | 定时器
  deleteCode: function (e) {
    var that = this;
    setInterval(function () {
      for (var i = 0; i < that.data.textarea.length; i++) {
        if (that.data.cursor == i) {} else {
          if (this.data.textarea.charAt(this.data.cursor) == '|') {
            that.data.textarea.replace('|', '')
          }
        }
      }
      if (that.data.guangbiao == false) {}
    }, 100)
  },
  btn_clear: function () {
    this.setData({
      textarea: ""
    })
  },
  /**
   * 获取点击的 按钮 ,并将值显示在 textarea
   */
  copyBtn: function (e) {
    var that = this;
    var now_args = e.currentTarget.dataset.set
    if (now_args == 'log'||now_args == 'pow') {
      now_args = now_args + '(?,?)'
    }
    if (now_args != "." && now_args != "π" && now_args != "e" && now_args != "lgamma" && now_args != "0" && now_args != "1" && now_args != "2" && now_args != "3" && now_args != "4" && now_args != "5" && now_args != "6" && now_args != "7" && now_args != "8" && now_args != "9" && now_args != "(" && now_args != ")" && now_args != "/" && now_args != "*" && now_args != "+" && now_args != "-" && now_args != "log(?,?)"&& now_args != "pow(?,?)") {
      now_args = now_args + '(?)'
    } else {

    }
    //将值添加到光标处:
    var textarea = this.data.textarea;
    var str = textarea.substring(0, this.data.cursor)
    var str2 = textarea.substring(this.data.cursor)
    // var textarea = "";
    if (this.data.cursor == 0) {
      var textarea = str2 + now_args;
      this.setData({
        textarea: textarea
      })
    } else {
      var textarea = str + now_args + str2;
      this.setData({
        textarea: textarea
      })
      // textarea = str + now_args + str2;

    }
    // var textarea = this.data.textarea + now_args;

  },

  bindTextAreaBlur: function (args) {
    console.log("bindTextAreaBlur!!!->" + args)
  },



  btn_submit: function (args) {
    console.log('btn_submit->args=', args)
    var that = this
    this.setData({
      textarea: this.data.textarea
    })
    console.log("textarea=", this.data.textarea)
    for (var i = 0; i < that.data.textarea.length; i++) {
      // console.log(i)
      if (that.data.textarea.charAt(i) == '|') {
        that.data.textarea = that.data.textarea.replace('|', '')
      }
      if (that.data.textarea.charAt(i) == '+') {
        that.data.textarea = that.data.textarea.replace('+', '%2B')
      }
      if (that.data.textarea.charAt(i) == '(') {
        that.data.textarea = that.data.textarea.replace('(', '%28')
      }
      if (that.data.textarea.charAt(i) == ')') {
        that.data.textarea = that.data.textarea.replace(')', '%29')
      }
    }
    var biaodashi = this.data.textarea;
    console.log(app.globalData.address + "getNum?content='" + that.data.textarea + "'");
    wx.request({
      url: app.globalData.address + 'getNum?content="' + that.data.textarea + '"',
      // data:{
      //   content:that.data.textarea
      // },
      timeout: 150000,
      success: function (args) {
        console.log('success=>', args)
        that.setData({
          result: args.data
        })
      }
    })
    that.btn_clear()
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  }
})

3.springboot重点代码展示

1.先把python的jar包放上来吧

<dependency>
            <groupId>org.python</groupId>
            <artifactId>jython-standalone</artifactId>
            <version>2.7.2</version>
        </dependency>

2.controller 类
该类接收来自网络上的包

import com.example.demo.Util.JiSuan_Util;
import org.python.antlr.ast.Str;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class JiSuanQiController {

    @RequestMapping("getNum")
    public @ResponseBody
    String getJiSuanQi(@RequestParam(value = "content",required = false) String content){
        //主要处理一些出现的字符, 
        content=content.replace("\"","");
        content=content.replace("|","");
        //exp是因为自己代码的匹配原则,与e冲突。
        content=content.replace("exp","ttt");
        //三个是转义字符传递 
        content=content.replace("%2B","+");
        content=content.replace("%28","(");
        content=content.replace("%29",")");
        
        System.out.println(content);
        Object num=JiSuan_Util.getNum(content);
        System.out.println("JiSuan_Util--->"+num);
        return num.toString();
    }
    
}

3.两个工具类,实现连接python,及接收返回结果
(1) JiSuan_Util.java

import org.python.core.PyFunction;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.util.PythonInterpreter;

/**
 * 实现功能 将前端传进来的表达式 ,进行优化 函数表达式 前面加上 math. 关键字 提交 python处理
 */
public class JiSuan_Util {

    public static PythonInterpreter interpreter = new PythonInterpreter();

    /**
     * python 处理 表达式 并返回结果
     */
    public static Object getNum(String expression){
        interpreter.execfile("/jisuanqi.py");
//        interpreter.execfile("D:\\D\\python空间\\微信小程序\\计算器\\计算器.py");
        // 第一个参数为期望获得的函数(变量)的名字,第二个参数为期望返回的对象类型
        PyFunction pyFunction = interpreter.get("add", PyFunction.class);
        //调用函数,如果函数需要参数,在Java中必须先将参数转化为对应的“Python类型”
        PyObject pyobj = pyFunction.__call__(new PyString(processExpression(expression)));
        System.out.println("the anwser is: " + pyobj);
        return pyobj;
    }

    /**
     * 加工表达式
     */
    public static String processExpression(String expression){

        System.out.println("processExpression->"+expression);
        String str = expression;
        for(int i = 0; i< MyMath.getMyMath().size(); i++){
        str = str.replace(MyMath.getMyMath().get(i).getWx(),MyMath.getMyMath().get(i).getPython());
            System.out.println("str->"+str);
        }
        System.out.println(str);
        return str;
    }

}

(2)MyMath.java

import java.util.ArrayList;

public class MyMath {

    public String wx;
    public String python;

    public MyMath(String wx, String python) {
        this.wx = wx;
        this.python = python;
    }

    public String getWx() {
        return wx;
    }

    public void setWx(String wx) {
        this.wx = wx;
    }

    public String getPython() {
        return python;
    }

    public void setPython(String python) {
        this.python = python;
    }

    @Override
    public String toString() {
        return "MyMath{" +
                "wx='" + wx + '\'' +
                ", python='" + python + '\'' +
                '}';
    }

    /**
     * 注:pow 函数为两个参数
     * @return
     */
    public static ArrayList<MyMath> getMyMath() {
        ArrayList<MyMath> list = new ArrayList<MyMath>();
        //绝对值
        list.add(new MyMath("fabs","math.fabs"));
        //以一个整数返回 x 的阶乘。 如果 x 不是整数或为负数时则将引发 ValueError。
        list.add(new MyMath("factorial","math.factorial"));
        //返回给定的整数参数的最大公约数。 如果有一个参数非零,则返回值将是能同时整除所有参数的最大正整数。 如果所有参数为零,则返回值为 0。 不带参数的 gcd() 返回 0。
        list.add(new MyMath("gcd","math.gcd"));
        //返回给定的整数参数的最小公倍数。 如果所有参数均非零,则返回值将是为所有参数的整数倍的最小正整数。 如果参数之一为零,则返回值为 0。 不带参数的 lcm() 返回 1。
        list.add(new MyMath("lcm","math.lcm"));

        //使用一个参数,返回 x 的自然对数(底为 e )。[自定义补充:必须为一个参数]
        //将返回 x 的 y 次幂。  该值参数为两个
        list.add(new MyMath("pow","math.pow"));
        //返回 x 的平方根。
        list.add(new MyMath("sqrt","math.sqrt"));

        //三角函数
        //返回以弧度为单位的 x 的反余弦值。 结果范围在 0 到 pi 之间。
        list.add(new MyMath("acos","math.acos"));
        //返回以弧度为单位的 x 的反正弦值。 结果范围在 -pi/2 到 pi/2 之间。
        list.add(new MyMath("asin","math.asin"));
        //返回以弧度为单位的 x 的反正切值。 结果范围在 -pi/2 到 pi/2 之间。
        list.add(new MyMath("atan","math.atan"));
        //返回 x 弧度的余弦值。
        list.add(new MyMath("cos","math.cos"));
        list.add(new MyMath("sin","math.sin"));
        list.add(new MyMath("atan","math.atan"));

        //角度弧度转换
        //将角度 x 从弧度转换为度数
        list.add(new MyMath("degrees","math.degrees"));
        //角度 x 从度数转换为弧度。将
        list.add(new MyMath("radians","math.radians"));

        //双曲函数:
        //返回 x 的反双曲余弦值
        list.add(new MyMath("acosh","math.acosh"));
        //返回 x 的反双曲正弦值。
        list.add(new MyMath("asinh","math.asinh"));
        //返回 x 的反双曲正切值。
        list.add(new MyMath("atanh","math.atanh"));
        //返回 x 的双曲余弦值。
        list.add(new MyMath("cosh","math.cosh"));
        //返回 x 的双曲正弦值。
        list.add(new MyMath("sinh","math.sinh"));
        //返回 x 的双曲正切值。
        list.add(new MyMath("tanh","math.tanh"));

        //返回 x 处的 伽马函数 值。
        list.add(new MyMath("gamma","math.gamma"));
        //返回Gamma函数在 x 绝对值的自然对数。
        list.add(new MyMath("lgamma","math.lgamma"));

        //常量
        list.add(new MyMath("π","math.pi"));
        list.add(new MyMath("e","math.e"));
        list.add(new MyMath("lgamma","math.lgamma"));
        list.add(new MyMath("log","math.log"));
        //返回 e 次 x 幂
        list.add(new MyMath("ttt","math.exp"));
        return list;
    }

}
  1. python代码 很简单(三行)
import math

def calculator(a):

    return eval(a)

四、心得

  1. 本文中 微信小程序 只是将算式表达式传递给java,由java处理完成,交给python计算结果。在这里,对算式表达式的处理,可以在三个地方,微信小程序,java,python。根据自己对哪个语言精通,可以调节。
  2. java中也有自己的math包,如果觉得python难,可以网上查阅一下。
  3. 微信小程序端 有个取巧指出,让用户自己书写函数,这样微信小程序 端将大大简单,但java 端难度将增大。