Как удалить бесполезные соединения в моем скрипте Python? - PullRequest
2 голосов
/ 08 января 2011

Я бы лучше использовал следующие примеры кодов, чтобы объяснить мою проблему:

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

Я написал очень длинный скрипт, и он используется для проверки состояния сайтов на разных сайтах (время отклика или тому подобное).), так же, как и в предыдущих кодах, я использую несколько потоков, чтобы проверить разные сайты отдельно.Как вы можете видеть, в каждом потоке будет несколько запросов к серверу, и, конечно, вы будете время от времени получать 403 или подобное.Я всегда думаю, что эти потерянные соединения (с исключениями) будут собираться каким-то сборщиком мусора в python, поэтому я просто оставляю их в покое.

Но когда я проверял свой сетевой монитор, я обнаружил, что эти потерянные соединения все еще расходуют ресурсы.Чем дольше выполняется скрипт, тем больше теряется подключений.Я действительно не хочу делать предложение try-exc каждый раз, когда отправляю запрос на сервер, чтобы в каждой части except можно было использовать del response для уничтожения потерянного соединения.Должен быть лучший способ сделать это, кто-нибудь может мне помочь?

Ответы [ 4 ]

3 голосов
/ 08 января 2011

Что именно, по вашему мнению, означает «удалить» в этом контексте, и что вы надеетесь достичь?

В Python есть автоматическая сборка мусора.Кроме того, эти объекты определены таким образом, что соединение будет закрываться всякий раз, когда сборщик мусора сможет собирать соответствующие объекты.

Если вы хотите, чтобы соединения закрывались, как только вы пересталиЕсли вам нужен объект, вы можете использовать конструкцию with.Например:

def CheckSite(Url1, Url2):
    with urllib2.urlopen(Url1) as Response1:
        with urllib2.urlopen(Url2) as Response2:
            # do stuff
1 голос
/ 08 января 2011

Я бы также предложил использовать оператор with вместе с функцией contextlib.closing.

Он должен закрывать соединение, когда завершает работу или получает исключение.

Что-то вроде:

with contextlib.closing(urllib2.open(url)) as reponse:
    pass
#del response    #to assure the connection does not have references...
0 голосов
/ 08 января 2011

Вы не должны проверять 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 /

Обратите внимание, что это выполняет то же самое, потому что в вашем коде, если Url1 завершится ошибкой, вы даже никогда не попытаетесь открыть соединение Url2.

** Примечание стороны ** Threading действительно не помогает вам здесь вообще.Вы также можете просто попробовать их последовательно, потому что одновременно будет работать только один поток.

http://dabeaz.blogspot.com/2009/08/inside-inside-python-gil-presentation.html
http://wiki.python.org/moin/GlobalInterpreterLock

0 голосов
/ 08 января 2011

Вы должны использовать Response1.close(). with не работает напрямую с urllib2.urlopen, но см. Пример contextlib.closing в документации по Python.

Соединения могут оставаться открытыми в течение нескольких часов, если они не закрыты должным образом, даже если процесс, создающий их, завершается из-за надежных функций доставки пакетов TCP.

...