Domanda

Ho uno script che recupera diverse pagine web e analizza le informazioni.

(Un esempio può essere visto a http://bluedevilbooks.com/search/ ? DEPT = matematica & CLASS = 103 & SEC = 01 )

Ho eseguito Cprofile su di esso, e, come ho assunto, urlopen prende un sacco di tempo. C'è un modo per recuperare le pagine più velocemente? O un modo per recuperare più pagine in una sola volta? Farò tutto ciò che è più semplice, in quanto Sono nuovo di pitone e sviluppo web.

Grazie in anticipo! :)

UPDATE: Ho una funzione chiamata fetchURLs(), che uso per fare una serie di necessità URL I così qualcosa come urls = fetchURLS().The URL sono tutti i file XML da Amazon e le API di eBay (che mi confonde il motivo per cui ci vuole così tanto tempo per il carico, forse il mio hosting è lento?)

Che cosa devo fare è di caricare ogni URL, leggere ogni pagina, e inviare i dati per un'altra parte dello script che analizzare e visualizzare i dati.

Si noti che non posso fare l'ultima parte fino a quando tutte le pagine sono state recuperate, questo è quello che il mio problema sia.

Inoltre, il mio ospite mi limiti a 25 processi alla volta, credo, per cui tutto ciò che è più facile sul server sarebbe bello:)


Qui è il tempo:

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)
È stato utile?

Soluzione

Modifica : Sto ampliando la risposta per includere un esempio più lucido. Ho trovato un sacco di ostilità e disinformazione in questo post per quanto riguarda V.S. threading async I / O. Perciò anche l'aggiunta più argomenti per confutare certo reclamo valido. Spero che questo vi aiuterà le persone a scegliere lo strumento giusto per il lavoro giusto.

Questa è una DUP a una domanda 3 giorni fa.

Python urllib2.open è lento, hanno bisogno di un modo migliore di leggere diversi URL - Stack Overflow    Python urllib2 .urlopen () è lento, hanno bisogno di un modo migliore di leggere diversi URL

Sto lucidatura il codice per mostrare come recuperare pagina web multiple in thread paralleli utilizzando.

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)

Come si può vedere, il codice specifica applicazione ha solo 3 linee, che possono essere ridotte in 1 linea se si è aggressivo. Io non credo che nessuno può giustificare la loro pretesa che questo è complesso e impossibile da mantenere.

Purtroppo la maggior parte altro codice filettatura postato qui ha alcuni difetti. Molti di loro fanno polling attivo aspettare che il codice alla fine. join() è un modo migliore per sincronizzare il codice. Credo che questo codice ha migliorato tutti gli esempi di threading finora.

connessione keep-alive

suggerimento di WoLpH sull'utilizzo di connessione keep-alive potrebbe essere molto utile se tutto quello che gli URL puntano allo stesso server.

contorto

Aaron Gallagher è un fan del quadro twisted e lui è ostile tutte le persone che suggeriscono thread. Purtroppo molte delle sue affermazioni sono disinformazione. Ad esempio ha detto "-1 per suggerire filettature Questo è IO-bound,.. Discussioni sono inutili qui" Questo in contrasto con le prove sia come Nick T e mi hanno dimostrato il guadagno di velocità dal thread utilizzando. In realtà io applicazione bound / O ha più da guadagnare dall'utilizzo di filo di Python (V.S. nessun guadagno in CPU applicazione bound). la critica sbagliata di Aaron sul passo di filettatura si è piuttosto confuso circa la programmazione parallela in generale.

strumento giusto per il lavoro giusto

Sono ben consapevole dei problemi riguardare parallela programmazione con le discussioni, pitone, asincrone di I / O e così via. Ogni strumento ha i suoi pro e contro. Per ogni situazione esiste uno strumento appropriato. Io non sono contro contorta (anche se non ho schierato uno io). Ma non credo che siamo in grado di flat out dire quel filo è male e contorto è buona in tutte le situazioni.

Per esempio, se il requisito del PO è quello di recuperare 10.000 sito in parallelo, async I / O sarà prefereable. Threading non sarà appropriabili (a meno che non magari con Stackless Python).

L'opposizione di Aaron per le discussioni sono per lo più generalizzazioni. Egli non riescono a riconoscere che questo è un compito banale parallelizzazione. Ogni attività è indipendente e non condividono risorse. Così la maggior parte del suo attacco non si applicano.

Dato il mio codice non ha alcuna dipendenza esterna, lo chiamerò strumento giusto per il lavoro giusto.

Performance

Credo che la maggior parte delle persone sarebbe d'accordo che le prestazioni di questo compito è in gran parte dipende dal codice di rete e il server esterno, in cui le prestazioni del codice della piattaforma dovrebbe avere effetto trascurabile. Tuttavia benchmark di Aaron mostrano un guadagno di velocità del 50% rispetto al codice threaded. Credo che sia necessario risposta a questo guadagno velocità apparente.

Codice di A Nick, c'è un difetto evidente che ha causato l'inefficienza. Ma come si spiega il guadagno di velocità 233ms sopra il mio codice? Credo che anche i fan contorte si asterranno da saltare in conclusione di attribuire questo per l'efficienza della contorta. Ci sono, dopo tutto, una quantità enorme di di fuori variabile del codice del sistema, come il prestazioni, rete, caching, e l'attuazione differenza tra urllib2 e client web contorto e così via server remoto.

Giusto per fare in modo di threading di Python non saràt incorrere in una quantità enorme di inefficienza, faccio un punto di riferimento rapido per deporre le uova 5 fili e poi 500 discussioni. Sono abbastanza comodo a dire il sovraccarico di deposizione delle uova 5 filo è trascurabile e non riesco a spiegare la differenza di velocità 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

Ulteriori test sui miei spettacoli fetching paralleli un enorme variabilità del tempo di risposta di 17 piste. (Purtroppo non ho contorto per verificare il codice di 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

Il mio test non supporta la conclusione di Aronne che threading è sempre più lento di async I / O con un margine misurabile. Dato il numero di variabili in gioco, devo dire che questo non è un test valido per misurare la differenza di prestazioni sistematica tra async I / O e la filettatura.

Altri suggerimenti

contorto ! Si fa questo genere di cose assurdamente facile rispetto a, per esempio, utilizzando thread.

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()

Questo codice esegue anche meglio di qualsiasi delle altre soluzioni distaccati (modificate dopo ho chiuso alcune cose che stavano usando un sacco di banda):

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

E utilizzando il codice di Nick T, truccate fino a anche dare la media di cinque e mostrare il migliore uscita:

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

E utilizzando il codice di Albert 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

ho devo dire, mi piace che i recuperi sequenziali eseguite migliore per me.

Ecco un esempio utilizzando python Threads. Gli altri esempi filettati qui lanciare un thread per ogni url, che non è un comportamento molto amichevole se provoca troppi risultati per il server per gestire (ad esempio è comune per i ragni di avere molti URL sullo stesso host)

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

Nota: I tempi qui indicati sono per 40 gli URL e dipenderanno molto dalla velocità della tua connessione Internet e la latenza al server. Essere in Australia, il mio ping è> 300ms

Con WORKERS=1 ci sono voluti 86 secondi per eseguire
Con WORKERS=4 ci sono voluti 23 secondi per eseguire
con WORKERS=10 ci sono voluti 10 secondi per eseguire

in modo da avere 10 thread download è 8,6 volte veloce come un unico filo.

Questa è una versione aggiornata che utilizza una coda. Ci sono almeno un paio di vantaggi.
1. Gli URL vengono richiesti nell'ordine in cui appaiono nella lista
2. Può usare q.join() per rilevare quando le richieste sono state tutte completate
3. I risultati sono mantenuti nello stesso ordine come l'elenco 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'attesa reale è probabilmente non in urllib2 ma nel server e / o la connessione di rete al server.

Ci sono 2 modi di accelerare questo.

  1. Mantenere la connessione attiva (vedi questa domanda su come farlo: Python urllib2 con mantenere vivo )
  2. l'uso Collegamenti multiplle, è possibile utilizzare fili o un approccio asincrono come Aaron Gallagher suggerito. Per questo, è sufficiente utilizzare qualsiasi esempio threading e si dovrebbe fare bene :) È inoltre possibile utilizzare il lib multiprocessing per rendere le cose abbastanza facile.

La maggior parte delle risposte si è concentrato sul recupero più pagine da diversi server allo stesso tempo (Filettatura), ma non il riutilizzo connessione HTTP già aperta. Se OP sta facendo richiesta multipla allo stesso server / sito.

In urlib2 una connessione separata viene creato con ogni richiesta che influisce sulle prestazioni e e come risultato più lento tasso di pagine andare a prendere. risolve urllib3 questo problema utilizzando un pool di connessioni. Possono trovare maggiori qui urllib3 [anche thread-safe]

Ci sono anche richieste rel="nofollow"> una libreria HTTP che usi urllib3

Questo, combinato con filettatura dovrebbe aumentare la velocità di recupero pagine

Al giorno d'oggi v'è eccellente Python lib che fare questo per voi chiamati href="http://docs.python-requests.org/" .

Usa API standard di richieste se si desidera soluzione basata su fili o asincrona API (utilizzando gevent sotto il cofano), se si desidera una soluzione basata sulla non-blocking IO.

Dal momento che questa domanda è stata pubblicata sembra che ci sia un più alto livello di astrazione a disposizione, ThreadPoolExecutor:

https://docs.python.org/3/ biblioteca / concurrent.futures.html # threadpoolexecutor-esempio

L'esempio da lì incollato qui per comodità:

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)))

C'è anche map che credo rende il codice più facile: https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Executor.map

Ray offre un modo elegante per fare questo (sia in Python 2 e Python 3) . Ray è una libreria per la scrittura in parallelo e distribuito Python.

È sufficiente definire la funzione fetch con il decoratore @ray.remote. Poi si può andare a prendere un URL in background chiamando 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])

Se si vuole anche di elaborare le pagine web in parallelo, è possibile inserire il codice di elaborazione direttamente nel fetch, oppure si può definire una nuova funzione remota e comporre insieme.

@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)

Se si dispone di un lungo elenco di URL che si desidera recuperare, si potrebbe desiderare di rilasciare alcuni compiti e poi elaborarli in modo da completare. È possibile farlo utilizzando 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()))

Ray documentazione .

Recupero pagine web, ovviamente, avrà un po 'come non si sta accedendo nulla locale. Se si dispone di più di accedere, è possibile utilizzare il threading modulo per eseguire una coppia a una volta.

Ecco un esempio molto grezzo

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])

Questa è stata l'uscita quando ho eseguito:

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

Afferrando i dati dal filo aggiungendo a una lista è probabilmente mal consigliato (coda sarebbe meglio), ma dimostra che c'è una differenza.

Ecco una soluzione libreria standard. Non è abbastanza veloce, ma utilizza meno memoria rispetto alle soluzioni filettati.

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())

Inoltre, se la maggior parte delle vostre richieste sono allo stesso host, quindi riutilizzare la stessa connessione http probabilmente di aiuto più di fare le cose in parallelo.

Si prega di trovare Python script di riferimento della rete per singola identificazione collegamento lentezza:

"""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))

E l'esempio dei risultati con 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 ha risultati molto simili.

In questo caso, DNS e lentezza urlopen sono facilmente identificabili.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top