如何删除python脚本中的无用连接?

时间:2011-01-08 15:57:00

标签: python garbage-collection urllib2

我最好使用以下示例代码来解释我的问题:

while True:
    NewThread = threading.Thread(target = CheckSite, args = ("http://example.com", "http://demo.com"))
    NewThread.start()

    time.sleep(300)

def CheckSite(Url1, Url2):
    try:
        Response1 = urllib2.urlopen(Url1)
        Response2 = urllib2.urlopen(Url2)
        del Response1
        del Response2
    except Exception, reason:
        print "How should I delete Response1 and Response2 when exception occurs?"
        del Response1
        del Response2 #### You can't simply write this as Reponse2 might not even exist if exception shows up running Response1

我写了一个非常looong脚本,它用于检查不同的站点运行状态(响应时间或类似的东西),就像我在之前的代码中所做的那样,我使用几个线程分别检查不同的站点。正如你在每个线程中看到的那样,会有几个服务器请求,当然你会偶尔得到403或类似的。我一直认为那些浪费的连接(有异常的连接)会被python中的某种垃圾收集器收集,所以我就把它们留下来了。

但是当我检查我的网络监视器时,我发现那些浪费的连接仍然在那里浪费资源。脚本运行的时间越长,出现的连接浪费就越多。我真的不希望每次发送服务器请求时都执行try-except子句,以便del response可以在每个except部分中使用{{1}}来销毁浪费的连接。有一个更好的方法来做到这一点,任何人都可以帮助我吗?

4 个答案:

答案 0 :(得分:3)

在这种情况下,你究竟期望“删除”是什么意思,无论如何,你希望实现什么?

Python具有自动垃圾收集功能。这些对象进一步定义,只要垃圾收集器到处收集相应的对象,就会关闭连接。

如果要确保在不再需要对象时立即关闭连接,可以使用with构造。例如:

def CheckSite(Url1, Url2):
    with urllib2.urlopen(Url1) as Response1:
        with urllib2.urlopen(Url2) as Response2:
            # do stuff

答案 1 :(得分:1)

我还建议将with语句与contextlib.closing函数一起使用。

它应该在完成作业或获得异常时关闭连接。

类似的东西:

with contextlib.closing(urllib2.open(url)) as reponse:
    pass
#del response    #to assure the connection does not have references...

答案 2 :(得分:0)

你应该使用Response1.close()with不能直接与urllib2.urlopen一起使用,但请参阅Python文档中的contextlib.closing示例。

由于TCP的可靠数据包传送功能,即使未正确关闭连接,连接仍可保持打开数小时,即使创建它们的进程已退出。

答案 3 :(得分:0)

您不应该检查Exception,而应该抓住URLError中提到的try: Response1 = urllib2.urlopen(Url1) Response2 = urllib2.urlopen(Url2) Response1.close() Response2.close() except URLError, reason: print "How should I delete Response1 and Response2 when exception occurs?" if Response2 is not None: Response2.close() elif Response1 is not None: Response1.close()

如果没有抛出异常,连接是否仍然存在?也许你正在寻找的是

def CheckSites(Url1, Url2):
    try:
        Response1 = urllib2.urlopen(Url1)
    except URLError, reason:
        print "Response 1 failed"
        return

    try:
        Response2 = urllib2.urlopen(Url2)
    except URLError, reason:
        print "Response 2 failed"
        ## close Response1
        Response1.close()
        ## do something or don't based on 1 passing and 2 failing
        return

    print "Both responded"
    ## party time.  rm -rf /

但我不明白你为什么要在一次尝试中封装它们。我个人会这样做。

{{1}}

请注意,这样做会完成同样的事情,因为在您的代码中,如果Url1失败,您甚至都不会尝试打开Url2连接。

**旁注** 线程真的没有帮助你。您也可以按顺序尝试它们,因为一次只能运行一个线程。

Documentation
http://dabeaz.blogspot.com/2009/08/inside-inside-python-gil-presentation.html