Maison  >  Article  >  développement back-end  >  Quel artefact ! Un framework de crawler Python efficace et plus facile à utiliser que les requêtes !

Quel artefact ! Un framework de crawler Python efficace et plus facile à utiliser que les requêtes !

WBOY
WBOYavant
2023-04-13 14:25:031421parcourir

Quel artefact ! Un framework de crawler Python efficace et plus facile à utiliser que les requêtes !

Récemment, le projet back-end Python de l'entreprise a été restructuré et toute la logique back-end a été fondamentalement modifiée pour utiliser des coroutines « asynchrones ». En regardant l'écran plein de code décoré avec async wait (l'implémentation de coroutines en Python), je me suis soudain senti confus et perdu.

Bien que j'aie déjà appris ce qu'est une "coroutine", je ne l'ai pas exploré en profondeur, j'ai donc juste profité de cette occasion pour l'apprendre attentivement.

C'est parti

Quel artefact ! Un framework de crawler Python efficace et plus facile à utiliser que les requêtes !

Qu'est-ce qu'une coroutine ?

En termes simples, les coroutines sont basées sur des threads mais sont plus légères que les threads. Pour le noyau système, les coroutines ont des caractéristiques invisibles, c'est pourquoi ce thread léger géré par les programmeurs qui écrivent leurs propres programmes est souvent appelé « thread de l'espace utilisateur ».

En quoi la coroutine est-elle meilleure que le multi-threading ?

1. Le contrôle du thread est entre les mains du système d'exploitation, tandis que le contrôle de la coroutine est entièrement entre les mains de l'utilisateur. Par conséquent, l'utilisation de coroutines peut réduire le changement de contexte lorsque le programme est en cours d'exécution et améliorer efficacement. l'efficacité du programme.

2. Lors de la création d'un thread, la taille de pile par défaut allouée au thread par le système est de 1 M, tandis que la coroutine est plus légère, proche de 1 K, donc plus de coroutines peuvent être ouvertes dans la même mémoire.

3. Étant donné que la nature des coroutines n'est pas multithread mais monothread, il n'est pas nécessaire d'avoir un mécanisme de verrouillage multithread. Puisqu'il n'y a qu'un seul thread, il n'y a pas de conflit causé par l'écriture simultanée de variables. Le contrôle des ressources partagées dans une coroutine ne nécessite pas de verrouillage, seul le statut doit être déterminé. Par conséquent, l'efficacité d'exécution des coroutines est bien supérieure à celle des multi-threads, et elle évite également efficacement la concurrence dans les multi-threads.

Scénarios applicables et inapplicables des coroutines

Scénarios applicables : les coroutines conviennent aux scénarios bloqués et nécessitent une grande quantité de concurrence.

Scénarios inapplicables : les coroutines ne conviennent pas aux scénarios comportant un grand nombre de calculs (car l'essence des coroutines est de basculer dans un seul thread). Si vous rencontrez cette situation, vous devez toujours utiliser d'autres moyens pour la résoudre). .

Exploration initiale du framework http asynchrone httpx

À ce stade, nous devrions avoir une compréhension générale des "coroutines", mais à ce stade de l'histoire, je crois que certains amis sont encore pleins de questions : comment les "coroutines" aident-elles test d'interface ? Ne vous inquiétez pas, la réponse est ci-dessous.

Je pense que les amis qui ont utilisé Python pour tester l'interface connaissent la bibliothèque de requêtes. La requête http implémentée dans les requêtes est une requête synchrone, mais en fait, sur la base des caractéristiques de blocage d'E/S des requêtes http, il est très approprié d'utiliser des coroutines pour implémenter des requêtes http « asynchrones » afin d'améliorer l'efficacité des tests.

Je pense que quelqu'un l'a remarqué il y a longtemps, donc après quelques explorations sur Github, comme prévu, j'ai finalement trouvé une bibliothèque open source qui prend en charge les coroutines pour appeler "de manière asynchrone" http: httpx.

Qu'est-ce que httpx

httpx est une bibliothèque open source qui hérite de presque toutes les fonctionnalités des requêtes et prend en charge les requêtes http "asynchrones". Pour faire simple, httpx peut être considéré comme une version améliorée des requêtes.

Maintenant, vous pouvez me suivre pour voir la puissance de httpx.

Installation

L'installation httpx est très simple et peut être exécutée dans un environnement Python 3.6 ou supérieur.

pip install httpx

Best Practices

Comme le dit le proverbe, l'efficacité détermine le succès ou l'échec. J'ai utilisé les méthodes httpx asynchrones et synchrones pour comparer la consommation de temps des requêtes http par lots. Jetons un coup d'œil aux résultats ~

Tout d'abord, jetons un coup d'œil aux performances chronophages des requêtes http synchrones :

import asyncio
import httpx
import threading
import time
def sync_main(url, sign):
 response = httpx.get(url).status_code
 print(f'sync_main: {threading.current_thread()}: {sign}2 + 1{response}')
sync_start = time.time()
[sync_main(url='http://www.baidu.com', sign=i) for i in range(200)]
sync_end = time.time()
print(sync_end - sync_start)

Le code est. relativement simple, vous pouvez voir Dans sync_main, l'accès http synchrone à Baidu a été implémenté 200 fois.

Le résultat après exécution est le suivant (une partie de la sortie clé est interceptée...) :

sync_main: <_MainThread(MainThread, started 4471512512)>: 192: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 193: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 194: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 195: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 196: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 197: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 198: 200
sync_main: <_MainThread(MainThread, started 4471512512)>: 199: 200
16.56578803062439

Vous pouvez voir que dans la sortie ci-dessus, le thread principal n'est pas commuté (car il s'agit d'un seul thread !) Le les requêtes sont exécutées dans l’ordre (car il s’agit d’une requête synchrone).

Le programme a pris un total de 16,6 secondes à exécuter.

Essayons la requête http "asynchrone" ci-dessous :

import asyncio
import httpx
import threading
import time
client = httpx.AsyncClient()
async def async_main(url, sign):
 response = await client.get(url)
 status_code = response.status_code
 print(f'async_main: {threading.current_thread()}: {sign}:{status_code}')
loop = asyncio.get_event_loop()
tasks = [async_main(url='http://www.baidu.com', sign=i) for i in range(200)]
async_start = time.time()
loop.run_until_complete(asyncio.wait(tasks))
async_end = time.time()
loop.close()
print(async_end - async_start)

Le code ci-dessus utilise le mot-clé async wait dans async_main pour implémenter le http "asynchrone", via asyncio (la bibliothèque io asynchrone demande la page d'accueil de Baidu 200 fois et imprime l'heure consommation) .

Après avoir exécuté le code, vous pouvez voir le résultat suivant (une partie de la sortie clé a été interceptée...).

async_main: <_MainThread(MainThread, started 4471512512)>: 56: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 99: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 67: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 93: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 125: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 193: 200
async_main: <_MainThread(MainThread, started 4471512512)>: 100: 200
4.518340110778809

Vous pouvez voir que bien que l'ordre soit foiré (56, 99, 67...) (c'est parce que le programme continue de basculer entre les coroutines), le thread principal ne change pas (les coroutines sont toujours de nature monothread ).

Le processus prend 4,5 secondes au total.

Par rapport aux 16,6 secondes que prend la requête synchrone, elle est raccourcie de près de 73% !

Comme le dit le proverbe, un pas est rapide et chaque pas est rapide. En termes de consommation de temps, le httpx « asynchrone » est en effet bien plus rapide que le http synchrone. Bien sûr, les « coroutines » peuvent non seulement permettre de tester l'interface en termes d'efficacité des requêtes.Après avoir maîtrisé les « coroutines », je pense que le niveau technique des amis peut également être amélioré à un niveau supérieur, concevant ainsi un meilleur cadre de test.

D'accord, c'est tout le contenu partagé aujourd'hui, si vous l'aimez, n'hésitez pas à l'aimer~

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer