实现频繁调用Python脚本的最佳方法

时间:2012-08-01 15:25:11

标签: php python mysql cron

我正在研究一些使用mechanize从另一个网站获取数据的python代码。由于网站的复杂性,代码需要10-30秒才能完成。它必须通过几页等工作。

我计划相当频繁地调用这段代码。我想知道实现这样的事情的最佳方法,而不会造成巨大的服务器负载。因为我对python很新,所以我不确定该语言是如何工作的。

如果代码正在处理一个请求而另一个用户调用代码,那么代码的两个实例是否可以同时运行?有没有更好的方法来实现这样的东西?

我希望以一种能够完成大量任务的方式进行设计,而不会对服务器造成太大的负担。

3 个答案:

答案 0 :(得分:1)

我的数据抓取脚本都使用缓存来最小化服务器上​​的负载。请务必使用HTTP工具,例如“If-Modified-Since”,“If-None-Match”和“Accept-Encoding:gzip”。

还要考虑使用多处理模块,以便您可以并行运行请求。

以下是我的下载程序脚本的摘录:

def urlretrieve(url, filename, cache, lock=threading.Lock()):
    'Read contents of an open url, use etags and decompress if needed'    

    request = urllib2.Request(url)
    request.add_header('Accept-Encoding', 'gzip')
    with lock:
        if ('etag ' + url) in cache:
            request.add_header('If-None-Match', cache['etag ' + url])
        if ('date ' + url) in cache:
            request.add_header('If-Modified-Since', cache['date ' + url])

    try:
        u = urllib2.urlopen(request)
    except urllib2.HTTPError as e:
        return Response(e.code, e.msg, False, False)
    content = u.read()
    u.close()

    compressed = u.info().getheader('Content-Encoding') == 'gzip'
    if compressed:
        content = gzip.GzipFile(fileobj=StringIO.StringIO(content), mode='rb').read()

    written = writefile(filename, content) 

    with lock:
        etag = u.info().getheader('Etag')
        if etag:
            cache['etag ' + url] = etag
        timestamp = u.info().getheader('Date')
        if timestamp:
            cache['date ' + url] = timestamp

    return Response(u.code, u.msg, compressed, written)

缓存是 shelve 的实例,是一个持久字典。

调用下载程序与多处理 Pool 实例上的imap_unordered()并行化。

答案 1 :(得分:0)

您可以一次运行多个python进程。至于导致服务器上的过度负载只能通过确保在任何给定时间只有一个实例运行或者其他一些进程(例如两个)来缓解。为此,您可以查看使用锁定文件或某种系统标志,互斥...等等

但是,限制过度使用的最佳方法是限制同时运行的任务数量。

答案 2 :(得分:0)

基本答案是“只要不共享关键资源(如数据库),就可以运行所需的程序实例”。

在实际环境中,您经常需要使用"multiprocessing module"并正确设计应用程序以处理并发性并避免损坏的状态或死锁。

顺便说一句,多进程应用程序的设计超出了StackOverflow上一个简单问题的范围......