为执行时间为30分钟的脚本制作网页接口
我写了一个Python脚本,用来处理一些CSV文件中的数据。这个脚本的运行时间根据CSV文件的大小不同,大概需要3到30分钟才能完成。
现在我想给这个脚本加一个网页界面,这样我就可以从任何地方上传CSV数据文件。我写了一个基本的HTTP POST上传页面,并使用了Python的CGI模块,但脚本运行一段时间后就超时了。
这个脚本在开始时会输出一些HTTP头信息,然后在处理CSV的每一行时输出一些数据。举个例子,这个打印语句大约每30秒会触发一次。
# at the very top, with the 'import's
print "Content-type: text/html\n\n Processing ... <br />"
# the really long loop.
for currentRecord in csvRecords:
count = count + 1
print "On line " + str(count) + " <br />"
我以为浏览器会收到这些头信息,然后继续等待,因为它会不断接收到一些小数据。但实际上似乎发生的情况是,浏览器根本没有收到任何数据,当处理一个包含很多行的CSV时,就会出现Error 504
超时错误。
也许在某个地方发生了缓存?从日志来看,
[Wed Jan 20 16:59:09 2010] [error] [client ::1] Script timed out before returning headers: datacruncher.py, referer: http://localhost/index.htm
[Wed Jan 20 17:04:09 2010] [warn] [client ::1] Timeout waiting for output from CGI script /Library/WebServer/CGI-Executables/datacruncher.py, referer: http://localhost/index.htm
解决这个问题的最好方法是什么?或者说,在浏览器中运行这样的脚本合适吗?
编辑:这个脚本是我自己用的,通常我打算在我的电脑上使用它,但我觉得一个基于网页的界面在旅行时或者从手机上使用会很方便。此外,实际上没有什么需要下载的内容——这个脚本最终很可能会通过电子邮件发送一份报告。
6 个回答
你可能需要使用 stdout.flush()
,因为在你写满一整页的数据之前,脚本其实并没有真正把任何东西写到网络服务器上,而这通常是在超时之前不会发生的。
不过,解决这个问题的正确方法是,像其他人建议的那样,把处理过程放在一个单独的线程或进程中,然后给用户展示一个自动刷新的页面,显示处理状态,可以加个进度条或者其他好看的视觉效果,让他们不会觉得无聊。
我之前遇到过这种情况,我使用了定时任务。HTTP脚本会把要执行的任务(比如数据库操作或者在某个文件夹里的文件)写入一个队列里,然后定时任务会读取这个队列,执行这些任务。
我会把工作分成以下几个部分:
首先需要一个网页应用的地址,这个地址可以接收上传的CSV文件。这个网页应用会把CSV文件里的内容放到一个离线队列里,比如说一个数据库表。网页应用的回应应该是一个唯一的ID,用来标识这个排队的项目(可以使用自动递增的ID列)。客户端需要保存这个ID,以便在第三部分使用。
接下来是一个独立的服务应用,它会定期检查这个队列,看看有没有需要处理的工作。处理完成后,会把结果存储到另一个数据库表里,使用之前的唯一ID作为关键字。
最后需要一个网页应用的地址,可以用来获取处理结果,格式是
http://server/getresults/uniqueid/
。如果处理已经完成(也就是说在结果数据库表里找到了这个唯一ID),那么就返回结果。如果还没完成,回应应该是一个代码来表示这个状态。比如可以用自定义的HTTP头,HTTP状态回应,或者回应内容写上'PENDING'(待处理)之类的。