I am trying to optimize this python script that is used to process web requests for machine translation. The actual translation executable that is called is quite fast. Also, the perl scripts that are called are fast as well.
The largest performance boost came from removing unnecessary import libraries. I would like to have this code reviewed so I can further optimize the performance. Also, I welcome any advice on a pythonic way of testing performance. My code is littered with timing and print commands that I removed for this post.
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import time
import sys
import cgi
import subprocess
import string
import xmlrpclib
reload(sys)
sys.setdefaultencoding('utf8')
isTestPerformance = len(sys.argv) == 4
# Parameters
if isTestPerformance:
source = sys.argv[1]
target = sys.argv[2]
sourceText = sys.argv[3]
else:
# this part is important to tell the browser that output is html text.
print "Access-Control-Allow-Origin: *"
print "Content-Type: text/plain;charset=utf-8"
print
form = cgi.FieldStorage()
sourceText = form.getvalue("sourceText").decode('utf8')
source = form.getvalue("source").lower()
target = form.getvalue("target").lower()
# Decode the CGI encoded source text
# NOTE: Custom encoding of semicolon (;), (?), (&), (#), etc, is only done here because
# CGI can not handle them. Do not used this (decode) if you are not using CGI,
# or use some other decoding that matches the encoding from the caller of this code
sourceText = sourceText.replace("__QUESTION_MARK__", "?")
sourceText = sourceText.replace("__SEMICOLON__", ";")
sourceText = sourceText.replace("__AMPERSAND__", "&")
sourceText = sourceText.replace("__NUMBER__", "#")
# sourceText = sourceText.replace("__NEWLINE__", "\n")
# Tokenize the Source Text
if source == "zh":
# Chinese has to do word alignment
# options are slim: write the text to a file
# use NLTK Stanford NLP (python>java) to segment chinese phrase
# then read the file and get the segmented phrase and continue
# TODO
# solution found (kinda) mini-segmenter
# https://github.com/alvations/mini-segmenter
import miniseg.minisegmenter as mini
src_tok = mini.segmenter(sourceText)
else:
cmd = "/usr/bin/perl"
perlscript = "/home/steve/mosesdecoder/scripts/tokenizer/tokenizer.perl"
option = "-l"
lang = source
proc = subprocess.Popen([cmd, perlscript, option, lang], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
proc.stdin.write(sourceText)
src_tok = proc.communicate()[0]
# print src_tok
# Build URL Proxy to call XML-RPC
if source == 'en' and target == 'zh':
port = '3001'
if source == 'en' and target == 'de':
port = '3002'
if source == 'en' and target == 'es':
port = '3003'
if source == 'en' and target == 'fr':
port = '3004'
if source == 'en' and target == 'it':
port = '3005'
if source == 'en' and target == 'nl':
port = '3006'
if source == 'en' and target == 'pl':
port = '3007'
if source == 'en' and target == 'pt':
port = '3008'
if source == 'en' and target == 'ro':
port = '3009'
if source == 'en' and target == 'ru':
port = '3010'
if source == 'en' and target == 'sl':
port = '3011'
if source == 'en' and target == 'hr':
port = '3012'
if source == 'en' and target == 'tr':
port = '3013'
if source == 'en' and target == 'ar':
port = '3014'
if source == 'en' and target == 'fa':
port = '3015'
if source == 'zh' and target == 'en':
port = '4001'
if source == 'de' and target == 'en':
port = '4002'
if source == 'es' and target == 'en':
port = '4003'
if source == 'fr' and target == 'en':
port = '4004'
if source == 'it' and target == 'en':
port = '4005'
if source == 'nl' and target == 'en':
port = '4006'
if source == 'pl' and target == 'en':
port = '4007'
if source == 'pt' and target == 'en':
port = '4008'
if source == 'ro' and target == 'en':
port = '4009'
if source == 'ru' and target == 'en':
port = '4010'
if source == 'sl' and target == 'en':
port = '4011'
if source == 'hr' and target == 'en':
port = '4012'
if source == 'tr' and target == 'en':
port = '4013'
if source == 'ar' and target == 'en':
port = '4014'
if source == 'fa' and target == 'en':
port = '4015'
url = "http://localhost:" + port + "/RPC2"
proxy = xmlrpclib.ServerProxy(url)
# Translate the Source Text
params = {"text": src_tok, "align": "false", "report-all-factors": "false"}
result = proxy.translate(params)
targetText = result['text'].encode('utf-8')
# Post-Process the Output
# TODO
if target == "zh":
# Chinese - Get rid of the spaces (word segmentation)
targetText = targetText.replace(" ", "")
# Post-Processes the translation output (regardless of language)
targetText = targetText.replace("__UNK__,", ",")
targetText = targetText.replace("__UNK__", " ")
#targetText = targetText.replace(" _ _ NEWLINE _ _ ", "\n")
targetText = targetText.replace(" ", " ")
if target in ["en", "fr", "es", "de", "it", "nl", "pl", "pt", "ro", "ru", "sl", "hr", "tr", "ar", "fa"]:
# Detokenize the target translation
cmd = "/usr/bin/perl"
perlscript = "/home/steve/mosesdecoder/scripts/tokenizer/detokenizer.perl"
option = "-l"
# lang = target
lang = "en" # THIS SHOULD BE target variable
proc = subprocess.Popen([cmd, perlscript, option, lang], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
proc.stdin.write(targetText)
targetText = proc.communicate()[0]
# Normalize Punctuation
# French -
# Detokenize the target translation
cmd = "/usr/bin/perl"
perlscript = "/home/steve/mosesdecoder/scripts/tokenizer/normalize-punctuation.perl"
option = "-l"
lang = target
proc = subprocess.Popen([cmd, perlscript, option, lang], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
proc.stdin.write(targetText)
targetText = proc.communicate()[0]
# True-case the target translation
# TODO: Do I need to true case the target output?
print targetText