2022年 12月 19日

在线 Python运行工具

    • 摘要
    • 准备
      • PHP环境设置
    • 原理
      • system方式
      • exec 方式
    • 源码
      • 核心
      • 完整代码
        • indexphp
        • callpyphp
        • temppy
    • 演示
      • 首页
      • 提示信息
      • 简要测试
        • 运行等待
      • 高级测试
      • 错误提示
    • 总结

摘要

昨天心血来潮,做了一个在线的PHP编辑工具 http://blog.csdn.net/marksinoberg/article/details/53869637 ,可以方便的练习PHP的基本语法,以及数据库的操作。结尾说可能会做一个Python版的在线编辑工具,那么说到做到。今天就写了个Python版的,供身边的同学以及初学者练习和使用。

准备

看过昨天的那篇博客的应该不难理解,这个工具背后的工作原理。

上传源码,运行脚本,反馈结果。

与之相比,这次的代码稍有些不同,毕竟昨天的是纯PHP代码之间的处理,而今天则是在PHP和Python之间的耦合。所以需要额外的增加一点处理。

PHP环境设置

在编码之前,应该先把PHP环境设置一下。具体来说就是修改一下php.ini文件。

去掉php.ini文件中的disable_functions前面的;,即可开启调用外部语言的拓展。

原理

这里说的原理,从狭义上来讲只是单纯的对于使用PHP调用Python代码。

一般来说有这么两种方式:

  • 通过system函数
  • 通过exec函数

这两个方法各有利弊,接下来将简单的介绍一下这两个函数的使用方法,至于怎么选择,按照自己的需求进行设置即可。

system方式

官方文档解释如下:
system官方文档

system函数本身具有打印命令执行输出的功能,也就是说,程序中的输出可在PHP页面中显示。

如果程序成功执行,则system的返回值为程序输出的最后一行,如果执行失败,返回false。

第二个参数是可选的,用来得到命令执行后的状态码,0表示成功调用外部程序,1表示调用失败。

exec 方式

官方文档有如下解释:
exec官方文档

exec ()函数与system()类似,也执行给定的命令,但不输出结果,而是返回结果的最后一行。

虽然它只返回命令结果的最后一行,但用第二个参数array 可以得到完整的结果,方法是把结果逐行追加到array的结尾处。

另外需要注意的是:只有指定了第二个参数时,才可以用第三个参数,用来取得命令执行的状态码。

源码

核心

核心思路如下:

  • 获取用户输入Python源码,然后上传到服务器上的temp.py文件。
  • 通过PHP调用外部的Python代码,执行相关脚本。
  • 前台通过ajax方式请求代码运行结果,并显示在result页面块上。

完整代码

index.php

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>郭璞 的在线Python工具</title>
  6. <link rel="shortcut icon" href="favicon.ico" type="image/x-ico" />
  7. <style>
  8. .container {
  9. width: 1356px;
  10. height: 640px;
  11. position: absolute;
  12. background: #CCC;
  13. }
  14. .left {
  15. width: 50%;
  16. height: 100%;
  17. background: lightgray;
  18. position: relative;
  19. float: left;
  20. }
  21. .header {
  22. width: auto;
  23. height: 61px;
  24. }
  25. input {
  26. width: 180px;
  27. height: 60px;
  28. position: relative;
  29. background: lightgreen;
  30. float: right;
  31. margin-right: 12px;
  32. margin-top: 6px;
  33. border-radius: 25px;
  34. box-shadow: 1px 1px 1px #6e6e6e;
  35. }
  36. .panel {
  37. width: 90%;
  38. height: 540px;
  39. align: center;
  40. }
  41. textarea {
  42. font-size: 22px;
  43. }
  44. .right {
  45. width: 50%;
  46. height: 100%;
  47. background: deepskyblue;
  48. position: relative;
  49. float: right;
  50. }
  51. </style>
  52. </head>
  53. <body>
  54. <div class="container">
  55. <div class="left">
  56. <div class="header">
  57. <label><font size="5">在下面写上您的<a href="#" id="tip">Python代码</a>.</font></label>
  58. <input id="btn_run" type="submit" value="点击运行"></input>
  59. </div>
  60. <hr>
  61. <div class="panel">
  62. <textarea id="source" style="width: 645px; height: 540px;"
  63. name="source" placeholder="echo 'Hello World!';">print "Hello 郭璞"
  64. </textarea>
  65. <!-- <textarea type="hidden" id="hidden" hidden></textarea> -->
  66. </div>
  67. </div>
  68. <div class="right">
  69. <h2>下面将显示出您的代码的执行结果</h2>
  70. <hr>
  71. <div class="panel">
  72. <textarea id="result" style="width: 645px; height: 540px;">
  73. </textarea>
  74. </div>
  75. </div>
  76. </div>
  77. <!-- 编写提交脚本,并获取返回结果 -->
  78. <script src="./js/jquery-2.2.4.min.js"></script>
  79. <script>
  80. // 请求运行结果
  81. function getResult() {
  82. document.getElementById("result").value = "代码正在运行中 ···";
  83. $.ajax({
  84. type : "GET",
  85. url : "./callpy.php",
  86. success : function(data) {
  87. document.getElementById("result").value = data;
  88. },
  89. error : function(err) {
  90. document.getElementById("result").value = err;
  91. }
  92. });
  93. }
  94. // 将源代码上传到服务器上
  95. function uploadSource() {
  96. var source = document.getElementById("source").value;
  97. $.ajax({
  98. type: "POST",
  99. url: "./index.php",
  100. data: {
  101. "source": source
  102. },
  103. success: function(){
  104. console.log("代码上传成功!");
  105. },
  106. error: function(err){
  107. console.log("代码上传失败!");
  108. alert(err);
  109. }
  110. });
  111. }
  112. // 使用ajax来 获取执行的结果
  113. $(document).ready(function() {
  114. document.getElementById("result").value = "正在获取运行结果··· ···";
  115. $("#btn_run").click(function(){
  116. // 先上传代码
  117. uploadSource();
  118. // 请求代码运行后的结果
  119. getResult();
  120. });
  121. });
  122. // 点击“Python代码”显示提示信息
  123. $(document).ready(function(){
  124. $("#tip").click(function(){
  125. document.getElementById("result").value = "您可以使用Python2.7.12以及向下兼容的Python语法。\n注意您的代码的缩进。另外,如果有需要连接数据库,请联系郭璞。QQ:1064319632";
  126. });
  127. });
  128. </script>
  129. <!-- 编写php脚本,获取提交信息 -->
  130. <?php
  131. $source = $_POST ['source'];
  132. $source = "#coding:utf8\n" . $source;
  133. file_put_contents ( "./temp.py", $source );
  134. ?>
  135. </body>
  136. </html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152

callpy.php

这里的调用外部代码需要的功能很简单,所以就选择了system函数啦。

  1. <?php
  2. $command = "python ./temp.py";
  3. $flag = system($command, $result);
  4. if($flag) {
  5. echo $result[0];
  6. }else{
  7. echo "不好意思,代码运行出错啦。\n\n\n您的语法有问题哟:\n请检查一下标点符号,代码缩进,单词拼写什么的吧!";
  8. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

temp.py

temp.py说白了就是个临时文件,所以每次代码被运行的时候都会被更新一遍。所以里面的内容不重要了。下面给出我测试过一次之后的temp.py的文件内容。

  1. #coding:utf8
  2. print "Hello 郭璞"
  3. from time import *
  4. print ctime()
  • 1
  • 2
  • 3
  • 4
  • 5

演示

下面就是激动人心的测试界面啦。

首页

首页部分

提示信息

点击左侧上方的“Python代码”的时候,会给出一点提示信息。如:
提示信息

简要测试

此在线编辑工具可以方便的进行Python脚本的编写。只要是符合正规的Python语法的,都是可以的。

运行等待

当编写的Python脚本比较的耗时的时候,前台需要给出提示信息,并进行等待。所以最好的方式就是显示一条“程序正在运行中··· ···”,这样既能给用户更好的体验,也能体现更加人性化的设计。
耗时任务

耗时任务结束后的结果显示

高级测试

高级测试

错误提示

上面全是介绍,代码正常运行的结果。但是很多时候我们并不能一下子就编写出bug free 的代码,所以适时的给出点提示是个不错的选择。但是这里给的建议就是自主发现错误,亲自手动的检查自己的代码,更能养成规范的代码编写习惯。

脚本出现错误时

总结

回顾一下,本次的实验核心就在于PHP调用外部程序的两个简单的方式。虽然各有利弊,但是找到合适的场景进行选择的话,还是能取得不错的效果的。

其实上面的全是些无关痛痒的话题啦。真正有用的是整合起来,PHP在网站开发上面有Python不可比拟的优势(虽然Python写起网站来一点也不虚)。但是Python的灵活又是PHP不可替代的。

通过今天这个测试,也不难想到了吧。倘若能恰当的将这两者进行整合,想必一定能做出一个既优雅,又高效的系统。

最后,我把这个工具上传到了自己的服务器上了。如果有想练习PHP语法,Python语法的意愿,可以和我取得联系。

联系方式在左侧的友情链接处可以找到。(^__^) 嘻嘻……