J'ai la fonction suivante que j'aimerais transformer en une fonction multi-thread:
{"dateadded": "2019-11-04 12:33:27", "url_status": "online", "tags": "elf", "url": "http://2.56.8.16/bins/arm7", "reporter": "Gandylyan1", "threat": "malware_download", "id": "251402"}
{"dateadded": "2019-11-04 12:33:25", "url_status": "online", "tags": "elf", "url": "http://2.56.8.16/bins/arm6", "reporter": "Gandylyan1", "threat": "malware_download", "id": "251401"}
En gros, elle va chercher dans un fichier JSON pour une valeur. Le problème principal est que le fichier est volumineux (plus de 50 Mo) et j'ai besoin de résultats le plus rapidement possible (plus de 7 secondes sont considérés comme trop).
Ceci est un extrait du fichier pour que vous puissiez voir la structure:
from __future__ import print_function
import os
import json
def url_searcher(value):
url_file_path = "C:\\Users\\Link\\Desktop\\"
for filename in os.listdir(url_file_path):
if filename == "url_list.json":
with open(url_file_path + filename) as f:
for line in f:
returnJson = json.loads(line)
if value in returnJson["url"]:
return returnJson
print(url_searcher("http://zadkay.com/blog/wwp/51065983.jpg"))
Question:
Quelles sont les étapes? Est-ce une bonne idée et cela améliorera-t-il la vitesse d'obtention d'un résultat?
Ici, vous pouvez voir un exemple JSON du fichier avec plus de lignes: https://pastebin.com/MXYTg1CV
Merci
3 Réponses :
Créer un thread en python est vraiment simple
import threading thread_one= threading.Thread(name='searcher', target=url_searcher, args=(value)) thread_one.start()
https://docs.python.org/3/library/threading.html
Mais je pense que cela ne réduira pas le temps de traitement, cela ne vous permettra que de lire plusieurs fichiers à la fois et peut même prendre plus de temps pour traiter chaque fichier.
La structure du fichier est toujours la même? Avez-vous essayé de le traiter sous forme de fichier texte brut et de rechercher le nom de la clé?
Ressemble à peu près à une opération limitée d'E / S:
from multiprocessing.dummy import Pool
from __future__ import print_function
from functools import partial
import json
import glob
def url_searcher(pathlist, value):
for filename in pathlist:
with open(filename) as f:
for line in f:
returnJson = json.loads(line)
if value in returnJson["url"]:
return returnJson
no_of_threads = 4 #can be set manually or allocated automatically by Pool (see docs)
url_file_path = "C:\\Users\\Link\\Desktop\\"
value = "very_important_stuff" #adjust to your liking!
workers = Pool(no_of_threads)
pathlist = [f for f in glob.iglob(url_file_path, recursive=recurse) if "url_list.json" in f]
result = workers.map(partial(url_searcher, value = value), pathlist)
workers.close()
workers.join()
Premièrement, mesurez, pas devinez. Familiarisez-vous avec snakeviz: https://jiffyclub.github.io/snakeviz/
with open(url_file_path + filename) as f:
for line in f:
# returnJson = json.loads(line)
# if value in returnJson["url"]:
# return returnJson
if value in line:
returnJson = json.loads(line)
return returnJson
Sur ma machine, 65% du temps est passé à la fonction décoder de decoder.py de la bibliothèque json.
Essayons une amélioration simple:
pip install snakeviz python -m cProfile -o program.prof my_program.py snakeviz program.prof
Sur ma machine, je vois une amélioration de 10 fois le temps d'exécution.
peut-être devriez-vous travailler avec du texte sans convertir de JSON en structure Python. Si l'URL est toujours au même endroit, vous pouvez la découper et vérifier si la valeur se trouve dans cette partie du texte.
peut-être que cela fonctionnera plus rapidement si vous utilisez simplement
if value in line:Je dois utiliser JSON car la même fonction s'appliquera à une structure différente. Key, Value est ce dont j'ai besoin ici, également à cause du retour qui doit être un json.
vous pouvez convertir une chaîne JSON en dictionnaire après avoir trouvé la valeur dans le texte
ok, mais qu'en est-il du multi-threading? est une bonne idée avec le code actuel?
pouvez-vous d'abord transformer les données en une structure de données plus appropriée? par exemple. un dictionnaire saisi par l '
url, ou une base de données avec un index appropriéPython a besoin d'un certain temps pour créer un
thread, et lesthreadspeuvent ne pas fonctionner en même temps en Python. Peut-être que multiprocessing.Pool fonctionnerait mieux. Vous devriez donc essayer de voir si cela vous aide.