1+ #!/usr/bin/env python3
2+ # -*- coding: utf-8 -*-
3+
4+ r'''
5+ learning.py
6+
7+ A Python 3 tutorial from http://www.liaoxuefeng.com
8+
9+ Usage:
10+
11+ python3 learning.py
12+ '''
13+
14+ import sys
15+
16+ def check_version ():
17+ v = sys .version_info
18+ if v .major == 3 and v .minor >= 4 :
19+ return True
20+ print ('Your current python is %d.%d. Please use Python 3.4.' % (v .major , v .minor ))
21+ return False
22+
23+ if not check_version ():
24+ exit (1 )
25+
26+ import os , io , json , subprocess , tempfile
27+ from urllib import parse
28+ from wsgiref .simple_server import make_server
29+
30+ EXEC = sys .executable
31+ PORT = 39093
32+ HOST = 'local.liaoxuefeng.com:%d' % PORT
33+ TEMP = tempfile .mkdtemp (suffix = '_py' , prefix = 'learn_python_' )
34+ INDEX = 0
35+
36+ def main ():
37+ httpd = make_server ('127.0.0.1' , PORT , application )
38+ print ('Ready for Python code on port %d...' % PORT )
39+ httpd .serve_forever ()
40+
41+ def get_name ():
42+ global INDEX
43+ INDEX = INDEX + 1
44+ return 'test_%d' % INDEX
45+
46+ def write_py (name , code ):
47+ fpath = os .path .join (TEMP , '%s.py' % name )
48+ with open (fpath , 'w' , encoding = 'utf-8' ) as f :
49+ f .write (code )
50+ print ('Code wrote to: %s' % fpath )
51+ return fpath
52+
53+ def decode (s ):
54+ try :
55+ return s .decode ('utf-8' )
56+ except UnicodeDecodeError :
57+ return s .decode ('gbk' )
58+
59+ def application (environ , start_response ):
60+ host = environ .get ('HTTP_HOST' )
61+ method = environ .get ('REQUEST_METHOD' )
62+ path = environ .get ('PATH_INFO' )
63+ if method == 'GET' and path == '/' :
64+ start_response ('200 OK' , [('Content-Type' , 'text/html' )])
65+ return [b'<html><head><title>Learning Python</title></head><body><form method="post" action="/run"><textarea name="code" style="width:90%;height: 600px"></textarea><p><button type="submit">Run</button></p></form></body></html>' ]
66+ if method == 'GET' and path == '/env' :
67+ start_response ('200 OK' , [('Content-Type' , 'text/html' )])
68+ L = [b'<html><head><title>ENV</title></head><body>' ]
69+ for k , v in environ .items ():
70+ p = '<p>%s = %s' % (k , str (v ))
71+ L .append (p .encode ('utf-8' ))
72+ L .append (b'</html>' )
73+ return L
74+ if host != HOST or method != 'POST' or path != '/run' or not environ .get ('CONTENT_TYPE' , '' ).lower ().startswith ('application/x-www-form-urlencoded' ):
75+ start_response ('400 Bad Request' , [('Content-Type' , 'application/json' )])
76+ return [b'{"error":"bad_request"}' ]
77+ s = environ ['wsgi.input' ].read (int (environ ['CONTENT_LENGTH' ]))
78+ qs = parse .parse_qs (s .decode ('utf-8' ))
79+ if not 'code' in qs :
80+ start_response ('400 Bad Request' , [('Content-Type' , 'application/json' )])
81+ return [b'{"error":"invalid_params"}' ]
82+ name = qs ['name' ][0 ] if 'name' in qs else get_name ()
83+ code = qs ['code' ][0 ]
84+ headers = [('Content-Type' , 'application/json' )]
85+ origin = environ .get ('HTTP_ORIGIN' , '' )
86+ if origin .find ('.liaoxuefeng.com' ) == - 1 :
87+ start_response ('400 Bad Request' , [('Content-Type' , 'application/json' )])
88+ return [b'{"error":"invalid_origin"}' ]
89+ headers .append (('Access-Control-Allow-Origin' , origin ))
90+ start_response ('200 OK' , headers )
91+ r = dict ()
92+ try :
93+ fpath = write_py (name , code )
94+ print ('Execute: %s %s' % (EXEC , fpath ))
95+ r ['output' ] = decode (subprocess .check_output ([EXEC , fpath ], stderr = subprocess .STDOUT , timeout = 5 ))
96+ except subprocess .CalledProcessError as e :
97+ r = dict (error = 'Exception' , output = decode (e .output ))
98+ except subprocess .TimeoutExpired as e :
99+ r = dict (error = 'Timeout' , output = '执行超时' )
100+ except subprocess .CalledProcessError as e :
101+ r = dict (error = 'Error' , output = '执行错误' )
102+ print ('Execute done.' )
103+ return [json .dumps (r ).encode ('utf-8' )]
104+
105+ if __name__ == '__main__' :
106+ main ()
0 commit comments