Question

J'ai un script qui va chercher plusieurs pages web et analyse l'info.

(Un exemple peut être vu à http://bluedevilbooks.com/search/ ? DEPT = MATH & CLASS = 103 & SEC = 01 )

Je courus cprofile là-dessus, et comme je supposais, urlopen prend beaucoup de temps. Est-il un moyen de récupérer les pages plus rapidement? Ou un moyen de chercher plusieurs pages à la fois? Je ferai tout ce qui est plus simple, comme je suis nouveau au développement de python et web.

Merci d'avance! :)

Mise à jour: J'ai une fonction appelée fetchURLs(), que j'utilise pour faire un tableau des URL je besoin donc quelque chose comme urls = fetchURLS().The URLS sont tous les fichiers XML et des API d'Amazon eBay (qui me confond à pourquoi il faut tant de temps à charger, peut-être est lent mon webhost?)

Ce que je dois faire est de charger chaque URL, lisez chaque page, et envoyer ces données à une autre partie du script qui analysera et afficher les données.

Notez que je ne peux pas faire la dernière partie jusqu'à ce que toutes les pages ont été tiré par les cheveux, c'est ce que ma question est.

En outre, mes limites d'accueil me à 25 processus à la fois, je crois, donc tout ce qui est plus facile sur le serveur serait bien:)


Ici, il est temps pour:

Sun Aug 15 20:51:22 2010    prof

         211352 function calls (209292 primitive calls) in 22.254 CPU seconds

   Ordered by: internal time
   List reduced from 404 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10   18.056    1.806   18.056    1.806 {_socket.getaddrinfo}
     4991    2.730    0.001    2.730    0.001 {method 'recv' of '_socket.socket' objects}
       10    0.490    0.049    0.490    0.049 {method 'connect' of '_socket.socket' objects}
     2415    0.079    0.000    0.079    0.000 {method 'translate' of 'unicode' objects}
       12    0.061    0.005    0.745    0.062 /usr/local/lib/python2.6/HTMLParser.py:132(goahead)
     3428    0.060    0.000    0.202    0.000 /usr/local/lib/python2.6/site-packages/BeautifulSoup.py:1306(endData)
     1698    0.055    0.000    0.068    0.000 /usr/local/lib/python2.6/site-packages/BeautifulSoup.py:1351(_smartPop)
     4125    0.053    0.000    0.056    0.000 /usr/local/lib/python2.6/site-packages/BeautifulSoup.py:118(setup)
     1698    0.042    0.000    0.358    0.000 /usr/local/lib/python2.6/HTMLParser.py:224(parse_starttag)
     1698    0.042    0.000    0.275    0.000 /usr/local/lib/python2.6/site-packages/BeautifulSoup.py:1397(unknown_starttag)
Était-ce utile?

La solution

EDIT : Je suis élargir la réponse à inclure un exemple plus poli. J'ai trouvé une hostilité de beaucoup et la désinformation dans ce post au sujet V.S. de filetage async I / O. Par conséquent, je également ajouter plus argument pour réfuter certaines allégations non valide. J'espère que ce peuple d'aide à choisir le bon outil pour le bon travail.

Ceci est un dup à une question il y a 3 jours.

Python urllib2.open est lent, besoin d'une meilleure façon de lire plusieurs urls - Stack Overflow    Python urllib2 .urlopen () est lent, besoin d'une meilleure façon de lire plusieurs urls

Je polir le code pour montrer comment récupérer page Web dans plusieurs threads parallèles à l'aide.

import time
import threading
import Queue

# utility - spawn a thread to execute target for each args
def run_parallel_in_threads(target, args_list):
    result = Queue.Queue()
    # wrapper to collect return value in a Queue
    def task_wrapper(*args):
        result.put(target(*args))
    threads = [threading.Thread(target=task_wrapper, args=args) for args in args_list]
    for t in threads:
        t.start()
    for t in threads:
        t.join()
    return result

def dummy_task(n):
    for i in xrange(n):
        time.sleep(0.1)
    return n

# below is the application code
urls = [
    ('http://www.google.com/',),
    ('http://www.lycos.com/',),
    ('http://www.bing.com/',),
    ('http://www.altavista.com/',),
    ('http://achewood.com/',),
]

def fetch(url):
    return urllib2.urlopen(url).read()

run_parallel_in_threads(fetch, urls)

Comme vous pouvez le voir, le code d'application spécifique a seulement 3 lignes, qui peuvent être regroupées en 1 ligne si vous êtes agressif. Je ne pense pas que quiconque puisse justifier leur affirmation selon laquelle c'est complexe et difficile à maintenir.

Malheureusement, la plupart des autres codes de filetage affiché ici a quelques défauts. Un grand nombre d'entre eux une relève d'attendre le code à la fin. join() est une meilleure façon de synchroniser le code. Je pense que ce code a amélioré tous les exemples de filetage jusqu'à présent.

Connexion keep-alive

suggestion de Wolph sur l'utilisation de connexion toujours en vie pourrait être très utile si vous tous les URL pointent vers le même serveur.

tordu

Aaron Gallagher est un fans de cadre twisted et il est hostile des gens qui suggèrent fil. Malheureusement, beaucoup de ses affirmations sont fausses informations. Par exemple, il a dit « -1 pour suggérer des fils Ceci est IO-lié;. Fils ne servent à rien ici. » Cette preuve contraire à la fois comme Nick T et je l'ai démontré gain de vitesse du fil à l'aide. En fait l'application liée E / S a le plus à gagner à l'aide du fil de Python (V.S. aucun gain dans l'application liée CPU). la critique erronée d'Aaron sur les émissions de fil, il est plutôt confus au sujet de la programmation parallèle en général.

bon outil pour le bon travail

Je suis bien conscient des problèmes se rapportent à la programmation parallèle en utilisant des fils, python, async E / S et ainsi de suite. Chaque outil a ses avantages et ses inconvénients. Pour chaque situation, il y a un outil approprié. Je ne suis pas contre tordu (bien que je ne l'ai pas déployé moi-même). Mais je ne crois pas que nous pouvons dire à plat que fil est mauvais et tordu est bon dans toutes les situations.

Par exemple, si l'exigence de l'OP est de chercher 10 000 site en parallèle, async E / S sera prefereable. Threading ne sera pas appropriable (sauf peut-être avec stackless Python).

L'opposition à des fils d'Aaron sont pour la plupart des généralisations. Il ne parviennent pas à reconnaître que la tâche est de parallélisation trivial. Chaque tâche est indépendant et ne partagent pas les ressources. Ainsi, la plupart de son attaque ne sont pas applicables.

Compte tenu de mon code n'a pas de dépendance externe, je vais l'appeler bon outil pour le bon travail.

Performance

Je pense que la plupart des gens seraient d'accord que l'exécution de cette tâche est dépendra en grande partie du code réseau et le serveur externe, où la performance du code de la plate-forme devrait avoir un effet négligeable. Cependant l'indice de référence Aaron montrent un gain de vitesse de 50% par rapport au code threadé. Je pense qu'il est nécessaire de répondre à ce gain de vitesse apparente.

Dans le code de Nick, il y a un défaut évident qui a causé l'inefficacité. Mais comment expliquez-vous le gain de vitesse de 233ms sur mon code? Je pense que même les fans tordus éviteront de sauter en conclusion à attribuer à l'efficacité de torsion. Il y a, après tout, une énorme quantité de l'extérieur du code de variable système, comme la performance du serveur distant, le réseau, la mise en cache et la mise en œuvre de différence entre urllib2 et client Web tordu et ainsi de suite.

Juste pour vous assurer que le filetage de Python net encourra une énorme quantité d'inefficacité, je fais une référence rapide pour frayer 5 fils, puis 500 threads. Je suis tout à fait à l'aise de dire les frais généraux de fraie 5 fil est négligeable et ne peut pas expliquer la différence de vitesse de 233ms.

In [274]: %time run_parallel_in_threads(dummy_task, [(0,)]*5)
CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
Wall time: 0.00 s
Out[275]: <Queue.Queue instance at 0x038B2878>

In [276]: %time run_parallel_in_threads(dummy_task, [(0,)]*500)
CPU times: user 0.16 s, sys: 0.00 s, total: 0.16 s
Wall time: 0.16 s

In [278]: %time run_parallel_in_threads(dummy_task, [(10,)]*500)
CPU times: user 1.13 s, sys: 0.00 s, total: 1.13 s
Wall time: 1.13 s       <<<<<<<< This means 0.13s of overhead

D'autres tests sur mes parallèles fetching montre une grande variabilité dans le temps de réponse en 17 courses. (Malheureusement, je ne l'ai pas tordu de vérifier le code d'Aaron).

0.75 s
0.38 s
0.59 s
0.38 s
0.62 s
1.50 s
0.49 s
0.36 s
0.95 s
0.43 s
0.61 s
0.81 s
0.46 s
1.21 s
2.87 s
1.04 s
1.72 s

Mon test ne supporte pas la conclusion d'Aaron que le filetage est toujours plus lent que async E / S par une marge mesurable. Compte tenu du nombre de variables impliquées, je dois dire que ce n'est pas un test valide pour mesurer la différence de performance systématique entre et async E / S filetage.

Autres conseils

Utilisez tordu! Il fait ce genre de chose absurdement facile par rapport à, par exemple, l'utilisation de threads.

from twisted.internet import defer, reactor
from twisted.web.client import getPage
import time

def processPage(page, url):
    # do somewthing here.
    return url, len(page)

def printResults(result):
    for success, value in result:
        if success:
            print 'Success:', value
        else:
            print 'Failure:', value.getErrorMessage()

def printDelta(_, start):
    delta = time.time() - start
    print 'ran in %0.3fs' % (delta,)
    return delta

urls = [
    'http://www.google.com/',
    'http://www.lycos.com/',
    'http://www.bing.com/',
    'http://www.altavista.com/',
    'http://achewood.com/',
]

def fetchURLs():
    callbacks = []
    for url in urls:
        d = getPage(url)
        d.addCallback(processPage, url)
        callbacks.append(d)

    callbacks = defer.DeferredList(callbacks)
    callbacks.addCallback(printResults)
    return callbacks

@defer.inlineCallbacks
def main():
    times = []
    for x in xrange(5):
        d = fetchURLs()
        d.addCallback(printDelta, time.time())
        times.append((yield d))
    print 'avg time: %0.3fs' % (sum(times) / len(times),)

reactor.callWhenRunning(main)
reactor.run()

Ce code aussi une meilleure performance que l'une des autres solutions déposés (éditées après avoir fermé certaines choses qui utilisaient la bande passante):

Success: ('http://www.google.com/', 8135)
Success: ('http://www.lycos.com/', 29996)
Success: ('http://www.bing.com/', 28611)
Success: ('http://www.altavista.com/', 8378)
Success: ('http://achewood.com/', 15043)
ran in 0.518s
Success: ('http://www.google.com/', 8135)
Success: ('http://www.lycos.com/', 30349)
Success: ('http://www.bing.com/', 28611)
Success: ('http://www.altavista.com/', 8378)
Success: ('http://achewood.com/', 15043)
ran in 0.461s
Success: ('http://www.google.com/', 8135)
Success: ('http://www.lycos.com/', 30033)
Success: ('http://www.bing.com/', 28611)
Success: ('http://www.altavista.com/', 8378)
Success: ('http://achewood.com/', 15043)
ran in 0.435s
Success: ('http://www.google.com/', 8117)
Success: ('http://www.lycos.com/', 30349)
Success: ('http://www.bing.com/', 28611)
Success: ('http://www.altavista.com/', 8378)
Success: ('http://achewood.com/', 15043)
ran in 0.449s
Success: ('http://www.google.com/', 8135)
Success: ('http://www.lycos.com/', 30349)
Success: ('http://www.bing.com/', 28611)
Success: ('http://www.altavista.com/', 8378)
Success: ('http://achewood.com/', 15043)
ran in 0.547s
avg time: 0.482s

Et en utilisant le code de Nick T, bricolé aussi donner à la moyenne des cinq et mieux montrer la sortie:

Starting threaded reads:
...took 1.921520 seconds ([8117, 30070, 15043, 8386, 28611])
Starting threaded reads:
...took 1.779461 seconds ([8135, 15043, 8386, 30349, 28611])
Starting threaded reads:
...took 1.756968 seconds ([8135, 8386, 15043, 30349, 28611])
Starting threaded reads:
...took 1.762956 seconds ([8386, 8135, 15043, 29996, 28611])
Starting threaded reads:
...took 1.654377 seconds ([8117, 30349, 15043, 8386, 28611])
avg time: 1.775s

Starting sequential reads:
...took 1.389803 seconds ([8135, 30147, 28611, 8386, 15043])
Starting sequential reads:
...took 1.457451 seconds ([8135, 30051, 28611, 8386, 15043])
Starting sequential reads:
...took 1.432214 seconds ([8135, 29996, 28611, 8386, 15043])
Starting sequential reads:
...took 1.447866 seconds ([8117, 30028, 28611, 8386, 15043])
Starting sequential reads:
...took 1.468946 seconds ([8153, 30051, 28611, 8386, 15043])
avg time: 1.439s

Et en utilisant le code de Yip Wai Tung:

Fetched 8117 from http://www.google.com/
Fetched 28611 from http://www.bing.com/
Fetched 8386 from http://www.altavista.com/
Fetched 30051 from http://www.lycos.com/
Fetched 15043 from http://achewood.com/
done in 0.704s
Fetched 8117 from http://www.google.com/
Fetched 28611 from http://www.bing.com/
Fetched 8386 from http://www.altavista.com/
Fetched 30114 from http://www.lycos.com/
Fetched 15043 from http://achewood.com/
done in 0.845s
Fetched 8153 from http://www.google.com/
Fetched 28611 from http://www.bing.com/
Fetched 8386 from http://www.altavista.com/
Fetched 30070 from http://www.lycos.com/
Fetched 15043 from http://achewood.com/
done in 0.689s
Fetched 8117 from http://www.google.com/
Fetched 28611 from http://www.bing.com/
Fetched 8386 from http://www.altavista.com/
Fetched 30114 from http://www.lycos.com/
Fetched 15043 from http://achewood.com/
done in 0.647s
Fetched 8135 from http://www.google.com/
Fetched 28611 from http://www.bing.com/
Fetched 8386 from http://www.altavista.com/
Fetched 30349 from http://www.lycos.com/
Fetched 15043 from http://achewood.com/
done in 0.693s
avg time: 0.715s

Je dois dire ai, je aime que les récupérations successives effectuées mieux pour moi.

Voici un exemple en utilisant Threads python. Les autres exemples ici taraudés lancent un fil par URL, ce qui est un comportement très sympathique si elle fait trop de résultats pour le serveur pour gérer (par exemple, il est fréquent que les araignées ont de nombreux liens sur le même hôte)

from threading import Thread
from urllib2 import urlopen
from time import time, sleep

WORKERS=1
urls = ['http://docs.python.org/library/threading.html',
        'http://docs.python.org/library/thread.html',
        'http://docs.python.org/library/multiprocessing.html',
        'http://docs.python.org/howto/urllib2.html']*10
results = []

class Worker(Thread):
    def run(self):
        while urls:
            url = urls.pop()
            results.append((url, urlopen(url).read()))

start = time()
threads = [Worker() for i in range(WORKERS)]
any(t.start() for t in threads)

while len(results)<40:
    sleep(0.1)
print time()-start

Note: Les temps donnés ici sont 40 urls et dépendra beaucoup de la vitesse de votre connexion Internet et le temps d'attente sur le serveur. Être en Australie, mon ping est> 300ms

Avec WORKERS=1 il a fallu 86 secondes pour exécuter
Avec WORKERS=4 il a fallu 23 secondes pour exécuter
avec WORKERS=10 il a fallu 10 secondes pour exécuter

afin d'avoir 10 fils téléchargement est de 8,6 fois plus vite que d'un seul fil.

Voici une version améliorée qui utilise une file d'attente. Il y a au moins deux avantages.
1. Les urls sont demandés dans l'ordre qu'ils apparaissent dans la liste
2. Peut utiliser q.join() pour détecter lorsque les demandes ont tous terminé
3. Les résultats sont conservés dans le même ordre que la liste url

from threading import Thread
from urllib2 import urlopen
from time import time, sleep
from Queue import Queue

WORKERS=10
urls = ['http://docs.python.org/library/threading.html',
        'http://docs.python.org/library/thread.html',
        'http://docs.python.org/library/multiprocessing.html',
        'http://docs.python.org/howto/urllib2.html']*10
results = [None]*len(urls)

def worker():
    while True:
        i, url = q.get()
        # print "requesting ", i, url       # if you want to see what's going on
        results[i]=urlopen(url).read()
        q.task_done()

start = time()
q = Queue()
for i in range(WORKERS):
    t=Thread(target=worker)
    t.daemon = True
    t.start()

for i,url in enumerate(urls):
    q.put((i,url))
q.join()
print time()-start

L'attente réelle est probablement pas urllib2 mais dans le serveur et / ou votre connexion réseau au serveur.

Il y a 2 façons d'accélérer cela.

  1. maintenir la connexion (voir cette question sur la façon de le faire: Python avec urllib2 garder en vie )
  2. Utiliser les connexions multiplle, vous pouvez utiliser les threads ou une approche async comme Aaron Gallagher suggéré. Pour cela, il suffit d'utiliser aucun exemple de filetage et vous devriez faire bien :) Vous pouvez également utiliser la lib multiprocessing pour rendre les choses assez facile.

La plupart des réponses axé sur la récupération de plusieurs pages de différents serveurs en même temps (Filetage), mais pas sur la réutilisation connexion HTTP déjà ouvert. Si OP fait une demande multiple au même serveur / site.

urlib2 une connexion séparée est créée pour chaque demande qui affecte la performance et à la suite et vitesse plus lente de pages allant chercher. urllib3 permet de résoudre ce problème en utilisant un pool de connexion. Peut lire plus ici urllib3 [thread-safe également]

Il y a aussi une bibliothèque HTTP utilisations urllib3

Ceci combiné avec le filetage devrait augmenter la vitesse des pages aller chercher

Aujourd'hui, il est excellent Python lib qui font cela pour vous appelé .

Utilisation api standard demandes si vous voulez une solution à base de fils ou async api (en utilisant gevent sous le capot) si vous voulez une solution basée sur la non-blocage IO.

Étant donné que cette question a été publiée il semble qu'il y ait un niveau abstraction disponible, ThreadPoolExecutor supérieur:

https://docs.python.org/3/ bibliothèque / concurrent.futures.html # ThreadPoolExecutor-exemple

L'exemple de là collé ici pour des raisons pratiques:

import concurrent.futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/']

# Retrieve a single page and report the url and contents
def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()

# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Start the load operations and mark each future with its URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))

Il y a aussi map que je pense rend le code plus facile: https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Executor.map

Ray offre une des façon élégante de le faire (dans les deux Python 2 et Python 3) . Ray est une bibliothèque pour l'écriture en parallèle et distribué Python.

Définissez simplement la fonction fetch avec le décorateur @ray.remote. Ensuite, vous pouvez chercher une URL dans l'arrière-plan en appelant fetch.remote(url).

import ray
import sys

ray.init()

@ray.remote
def fetch(url):
    if sys.version_info >= (3, 0):
        import urllib.request
        return urllib.request.urlopen(url).read()
    else:
        import urllib2
        return urllib2.urlopen(url).read()

urls = ['https://en.wikipedia.org/wiki/Donald_Trump',
        'https://en.wikipedia.org/wiki/Barack_Obama',
        'https://en.wikipedia.org/wiki/George_W._Bush',
        'https://en.wikipedia.org/wiki/Bill_Clinton',
        'https://en.wikipedia.org/wiki/George_H._W._Bush']

# Fetch the webpages in parallel.
results = ray.get([fetch.remote(url) for url in urls])

Si vous voulez aussi traiter les pages Web en parallèle, vous pouvez mettre le code de traitement directement dans fetch, ou vous pouvez définir une nouvelle fonction à distance et de les composer ensemble.

@ray.remote
def process(html):
    tokens = html.split()
    return set(tokens)

# Fetch and process the pages in parallel.
results = []
for url in urls:
    results.append(process.remote(fetch.remote(url)))
results = ray.get(results)

Si vous avez une très longue liste d'URL que vous voulez chercher, vous pouvez publier des tâches, puis les traiter dans l'ordre qu'ils complètent. Vous pouvez le faire en utilisant ray.wait.

urls = 100 * urls  # Pretend we have a long list of URLs.
results = []

in_progress_ids = []

# Start pulling 10 URLs in parallel.
for _ in range(10):
    url = urls.pop()
    in_progress_ids.append(fetch.remote(url))

# Whenever one finishes, start fetching a new one.
while len(in_progress_ids) > 0:
    # Get a result that has finished.
    [ready_id], in_progress_ids = ray.wait(in_progress_ids)
    results.append(ray.get(ready_id))
    # Start a new task.
    if len(urls) > 0:
        in_progress_ids.append(fetch.remote(urls.pop()))

Voir Ray documentation .

pages Web sera évidemment l'exactitude de prendre un certain temps que vous n'êtes pas accès à quoi que ce soit local. Si vous avez plusieurs d'accès, vous pouvez utiliser le module threading pour exécuter un couple à une fois.

Voici un exemple très brut

import threading
import urllib2
import time

urls = ['http://docs.python.org/library/threading.html',
        'http://docs.python.org/library/thread.html',
        'http://docs.python.org/library/multiprocessing.html',
        'http://docs.python.org/howto/urllib2.html']
data1 = []
data2 = []

class PageFetch(threading.Thread):
    def __init__(self, url, datadump):
        self.url = url
        self.datadump = datadump
        threading.Thread.__init__(self)
    def run(self):
        page = urllib2.urlopen(self.url)
        self.datadump.append(page.read()) # don't do it like this.

print "Starting threaded reads:"
start = time.clock()
for url in urls:
    PageFetch(url, data2).start()
while len(data2) < len(urls): pass # don't do this either.
print "...took %f seconds" % (time.clock() - start)

print "Starting sequential reads:"
start = time.clock()
for url in urls:
    page = urllib2.urlopen(url)
    data1.append(page.read())
print "...took %f seconds" % (time.clock() - start)

for i,x in enumerate(data1):
    print len(data1[i]), len(data2[i])

Ce fut la sortie quand je l'ai couru:

Starting threaded reads:
...took 2.035579 seconds
Starting sequential reads:
...took 4.307102 seconds
73127 19923
19923 59366
361483 73127
59366 361483

Saisissant les données du fil en ajoutant à une liste est probablement mal avisé (File d'attente serait mieux), mais il montre qu'il ya une différence.

Voici une solution de bibliothèque standard. Il est pas tout à fait aussi vite, mais il utilise moins de mémoire que les solutions filetés.

try:
    from http.client import HTTPConnection, HTTPSConnection
except ImportError:
    from httplib import HTTPConnection, HTTPSConnection
connections = []
results = []

for url in urls:
    scheme, _, host, path = url.split('/', 3)
    h = (HTTPConnection if scheme == 'http:' else HTTPSConnection)(host)
    h.request('GET', '/' + path)
    connections.append(h)
for h in connections:
    results.append(h.getresponse().read())

En outre, si la plupart de vos demandes sont au même hôte, réutiliser ensuite la même connexion http aurait probablement besoin d'aide plus que de faire des choses en parallèle.

S'il vous plaît trouver scénario de référence réseau Python pour l'identification de la lenteur de connexion unique:

"""Python network test."""
from socket import create_connection
from time import time

try:
    from urllib2 import urlopen
except ImportError:
    from urllib.request import urlopen

TIC = time()
create_connection(('216.58.194.174', 80))
print('Duration socket IP connection (s): {:.2f}'.format(time() - TIC))

TIC = time()
create_connection(('google.com', 80))
print('Duration socket DNS connection (s): {:.2f}'.format(time() - TIC))

TIC = time()
urlopen('http://216.58.194.174')
print('Duration urlopen IP connection (s): {:.2f}'.format(time() - TIC))

TIC = time()
urlopen('http://google.com')
print('Duration urlopen DNS connection (s): {:.2f}'.format(time() - TIC))

exemple de résultats avec Python 3.6:

Duration socket IP connection (s): 0.02
Duration socket DNS connection (s): 75.51
Duration urlopen IP connection (s): 75.88
Duration urlopen DNS connection (s): 151.42

Python 2.7.13 a des résultats très similaires.

Dans ce cas, le DNS et la lenteur urlopen sont facilement identifiables.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top