如何提升读取大文件并返回下载的Python CGI性能?

2 投票
4 回答
1785 浏览
提问于 2025-04-15 14:31

我有一个用Python写的CGI脚本,它会检查同一个IP地址访问的次数,如果没问题,就会从磁盘上读取一个很大的文件(11MB),然后把这个文件作为下载返回给用户。

这个脚本能工作,但速度很慢。问题似乎出在每次都要重复读取这个大文件上:

def download_demo():
    """
    Returns the demo file
    """

    file = open(FILENAME, 'r')
    buff = file.read()

    print "Content-Type:application/x-download\nContent-Disposition:attachment;filename=%s\nContent-Length:%s\n\n%s" %    (os.path.split(FILENAME)[-1], len(buff), buff)

我该怎么让这个过程更快呢?我想过用内存盘来存放这个文件,但肯定还有更好的解决办法。使用mod_wsgi代替CGI脚本会有帮助吗?这样我能把这个大文件放在Apache的内存空间里吗?

任何帮助都非常感谢。

4 个回答

1

试着一次读取和输出大约16KB的数据块。可能是Python在后台做了一些比较慢的操作,手动缓冲可能会更快。

你不需要使用比如说内存磁盘之类的,操作系统的磁盘缓存应该会为你缓存文件内容。

2

你为什么把所有内容都放在一个打印语句里呢?Python在处理这些内容的时候,需要生成几个临时字符串来处理标题。而因为最后的那个%s,Python还得把整个文件的内容存放在两个不同的字符串变量里。这种做法其实可以改进一下。

print "Content-Type:application/x-download\nContent-Disposition:attachment;filename=%s\nContent-Length:%s\n\n" %    (os.path.split(FILENAME)[-1], len(buff))
print buff

你也可以考虑使用原始输入输出模块来读取文件,这样Python就不会创建那些你并不需要的临时缓冲区了。

9

使用mod_wsgi,并且用类似下面的方式:

def application(environ, start_response):
    status = '200 OK'
    output = 'Hello World!'

    response_headers = [('Content-type', 'text/plain')]
    start_response(status, response_headers)

    file = open('/usr/share/dict/words', 'rb')
    return environ['wsgi.file_wrapper'](file)

换句话说,使用WSGI标准中的wsgi.file_wrapper扩展,这样可以让Apache和mod_wsgi更高效地发送文件内容,使用sendfile或mmap。这意味着你的应用程序根本不需要把文件读到内存里。

撰写回答