将Java更好地移植到Python的方法?
经过几个小时的努力,我终于把这个程序移植过来了,看起来现在可以正常工作了。不过,我想知道有没有人知道更好或者更完整的方法,把Java的servlet移植到Python里。Python脚本的开头有很多辅助代码,目的是为了让程序能逐行直接移植到Python中。有没有人知道更好的方法呢?
Java
// --------------------------------------------------------
// File: Hello.java
// Description: A simple "Hello World" servlet
// --------------------------------------------------------
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import sun.servlet.http.HttpServer;
public class Hello extends HttpServlet {
int count;
public void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// setup response
response.setContentType("text/html");
PrintWriter out = response.getWriter();
// send response
out.println("<html><body>");
out.println("<h5>Stephen Paul Chappell (SPC)</h5>");
out.println("<h5>:) (ZTD) Zero The Dragon :(</h5>");
String name = request.getParameter("NAME");
if (name != null && !name.equals("")) {
out.println("<h2>Hello, " + name + "</h2>");
} else {
out.println();
if (name != null && name.equals("")) {
out.println(" <h2>You didn't enter your name. Please enter your name. </h2>");
} else {
out.println(" <h2>What's your name? </h2>");
}
out.println(" <hr>");
out.println(" <form action=\"http://127.0.0.1:8080/servlet/Hello\">");
out.println();
out.println(" Enter your name: <input type=\"text\" name=\"NAME\" value=\"Fred\"><br>");
out.println(" <input type=\"submit\" value=\"Click for greeting\">");
out.println();
out.println(" </form>");
}
String color = request.getParameter("FAVCOLOR");
if (color != null) {
out.println("<h2>Why, " + color + " is my favorite color too!</h2>");
}
count++;
out.println("This page has been hit " + count + " time(s).");
out.print("</body></html>");
}
// start web server
public static void main(String[] args) throws Exception {
HttpServer.main(args);
}
}
Python
import urllib.parse
import http.server
import cgitb
import sys
import io
################################################################################
class HttpServlet(http.server.BaseHTTPRequestHandler):
__debug = False
@staticmethod
def debug(value):
HttpServlet.__debug = value
def do_GET(self):
if self.path == '/favicon.ico':
self.send_error(404)
return
request = HttpServletRequest(self.path)
response = HttpServletResponse()
try:
self.service(request, response)
except Exception:
if HttpServlet.__debug:
self.send_response(500)
self.send_header('Content-type', 'text/html')
self.end_headers()
klass, value, trace = sys.exc_info()
html = cgitb.html((klass, value, trace.tb_next))
self.wfile.write(html.encode())
else:
self.send_error(500)
else:
self.send_response(200)
self.send_header('Content-type', response._type)
self.end_headers()
self.wfile.write(response._value)
def service(self, request, response):
raise NotImplementedError()
################################################################################
class HttpServletRequest:
def __init__(self, path):
query = urllib.parse.urlparse(path).query
self.__dict = urllib.parse.parse_qs(query, True)
def getParameter(self, name):
return self.__dict.get(name, [None])[0]
################################################################################
class HttpServletResponse:
def __init__(self):
self.__content_type = 'text/plain'
self.__print_writer = PrintWriter()
def setContentType(self, content_type):
self.__content_type = content_type
def getWriter(self):
return self.__print_writer
@property
def _type(self):
return self.__content_type
@property
def _value(self):
return self.__print_writer.getvalue().encode()
################################################################################
class PrintWriter(io.StringIO):
print = io.StringIO.write
def println(self, string):
self.write(string + '\r\n')
################################################################################
class HttpServer(http.server.HTTPServer):
@staticmethod
def main(RequestHandlerClass, port=80):
server = HttpServer(('', port), RequestHandlerClass)
socket = server.socket.getsockname()
print('Serving HTTP on', socket[0], 'port', socket[1], '...')
try:
server.serve_forever()
except KeyboardInterrupt:
print('Keyboard interrupt received: EXITING')
server.server_close()
################################################################################
################################################################################
## ---------------------------------------------------------
## File: Hello.py
## Description: A simple "Hello World" servlet
## ---------------------------------------------------------
class Hello(HttpServlet):
count = 0
def service(self, request, response):
# Setup for a response.
response.setContentType('text/html')
out = response.getWriter()
# Send an appropriate response.
out.println('''\
<html>
<head>
<title>Java to Python servlet</title>
</head>
<body>
<h5>Stephen Paul Chappell (SPC)</h5>
<h5>:) (ZTD) Zero The Dragon :(</h5>''')
name = request.getParameter('NAME')
if name:
out.println('''\
<h2>Hello, {}!</h2>'''.format(name))
else:
if name == '':
out.println('''\
<h2>You did not enter your name.</h2>
<h3>Please enter your name.</h3>''')
else:
out.println('''\
<h2>What is your name?</h2>''')
out.println('''\
<form>
<fieldset>
<legend>About Yourself</legend>
<label for='NAME'>Enter your name:</label>
<input id='NAME' name='NAME' type='text' value='John Doe' />
<br />
<input type='submit' value='Click me!' />
</fieldset>
</form>''')
color = request.getParameter('FAVCOLOR')
if color:
out.println('''\
<h2>Why, {} is my favorite color too!</h2>'''.format(color))
Hello.count += 1
out.println('''\
This page has been hit {} times.'''.format(Hello.count))
out.print('''\
</body>
</html>''')
# Start the web server.
def main():
HttpServlet.debug(True)
HttpServer.main(Hello)
################################################################################
if __name__ == '__main__':
main()
如果有人好奇这个项目的目的,最初的Java程序是作为大一计算机科学课程的入门练习给出的。从那以后,我已经有大约六年没用过Java了,现在我在翻看旧程序,把它们移植到Python中,既是为了挑战自己,也是为了学习。移植servlet的时候遇到了一些额外的困难。
4 个回答
这不是翻译而是移植吗? :)
我刚刚在网上查了一下,发现了 java2python 以及 一个类似的问题。
无论如何……
理想情况下,我认为你应该理解你正在翻译的内容,这样你才能知道哪些部分需要翻译,哪些部分不需要。你需要对这两种语言有一定的了解,才能知道Java中的结构是如何与Python中的类似结构对应的,以及库在翻译中扮演的角色。
直接在两种语言之间翻译通常不是一个好方法。我提到这一点是因为你提问中翻译的Python代码并不是很符合Python的风格。而且,很多Python代码是与HTTP服务器相关的,这在Java代码中并不存在。因此,要想得到一个“公平”的翻译,我会依赖一个Python框架,让Python的功能类似于Java的Servlet容器。比如说 Tornado 或 Django。我的意思是,Java的Servlet有一套重要的标准,所以Python的版本也应该遵循类似的路线,这至少意味着要考虑 WSGI。
我最好的建议是不要逐行移植代码。Python和Java是两种不同的语言,如果你只是把Java风格的代码写成Python,那你会给自己带来麻烦。
这里有一些常见的差异和错误的入门知识:http://dirtsimple.org/2004/12/python-is-not-java.html
如果你有幸在一个包含单元测试的代码库中工作,一个很好的方法是把你的单元测试从Java移植到Python,然后再写新的Python代码来匹配这些单元测试。如果没有这样的条件,那么更重要的是要理解这个软件在Java中做了什么,然后用Python写出做同样事情的代码。这样做的方式几乎肯定不会是逐行对应的,至少在代码的每一行上不会。