Suite

Comment écrire dans une seule table via le multitraitement Python


Un commentaire dans le post Le multitraitement avec arcpy peut-il être exécuté dans un outil de script ? m'a fait réfléchir, car j'ai souvent besoin de faire exactement ceci:

Attention aux situations de blocage (deux curseurs Insert dans la même table par exemple)

Ma question est, comment pouvez-vous écrire dans une seule table lors de l'utilisation du multitraitement?

Voici un exemple de script, qui parcourt l'exemple de couche City et utilise le multitraitement pour copier les valeurs de chaque ville dans une table de sortie via un insertCursor (cela simplifie le scénario plus compliqué que j'ai en tête).

# Tester comment écrire dans une table fGDB de sortie via plusieurs threads import os, sys, arcpy, multiprocessing from multiprocessing import Process, Queue def Worker(input, output): pour func in iter(input.get, 'STOP'): entrées = func doProcess(inputs) def doProcess(inputs): outTblName = inputs[0] city = inputs[1] pop = inputs[2] avec arcpy.da.InsertCursor(os.path.join(arcpy.env.scratchGDB, outTblName ), ["NAME", "POPULATION"]) comme iCursor : essayez : iCursor.insertRow([city, pop]) sauf : print("Problème d'insertion " + city + " : " + str(pop) + " : essayant again" ) doProcess(inputs) if __name__ == '__main__': NUMBER_OF_PROCESSES = 8 task_queue = Queue() done_queue = Queue() inFC = "C:Program Files (x86)ArcGISDesktop10.2TemplateDataTemplateData. gdbWorldCity" outTblName = "testTable" #Créez la table vide outTable = os.path.join(arcpy.env.scratchGDB, outTblName) if(arcpy.Exists(outTable)): arcpy.Delete_management(outTable) arcpy. CreateTable_management(arcpy.env.scratchGDB, outTblName) arcpy.AddF ield_management(outTable, "Name", "TEXT") arcpy.AddField_management(outTable, "Population", "DOUBLE") #Itérer à travers les villes. Envoyez chacun au multiprocesseur avec arcpy.da.SearchCursor(inFC, ["NAME", "POPULATION"]) en tant que sCursor : pour la ville dans sCursor : cityName = city[0] pop = city[1] task_queue.put([ outTblName, cityName, pop]) pour i in range(NUMBER_OF_PROCESSES): Process(target=Worker, args=(task_queue, done_queue)).start() pour i in range(NUMBER_OF_PROCESSES): task_queue.put('STOP')

Comme prévu, il rencontre des problèmes lorsque plusieurs threads tentent d'accéder simultanément à la table de sortie. Même en appelant lefaireProcessfonctionner à nouveau de manière récursive après la détection d'erreurs, la table de sortie contient moins de lignes que la table d'entrée.

Une idée est que chaque thread crée une nouvelle table et les ajoute toutes à la fin. Existe-t-il des suggestions de bonnes pratiques ?


Je n'ai jamais essayé le multitraitement, j'ai décidé de l'essayer. Ce script :

import os, sys, arcpy, multiprocessing from arcpy import env env.overwriteoutput=1 scratchGDB=r'd:
ubbishTEST.gdb' def function(inputs): print ("got arg %s" % entrées) outTblName = entrées [0] ville = entrées[1] pop = entrées[2] avec arcpy.da.InsertCursor(os.path.join(scratchGDB, outTblName), ["NAME", "POPULATION"]) comme iCursor : essayez : iCursor. insertRow([city, pop]) sauf : print("Problème d'insertion " + city + " : " + str(pop) + " : try again" ) if __name__ == "__main__": number_of_cpus = 5 outTblName = "testTable" outTable = os.path.join(scratchGDB, outTblName) if(arcpy.Exists(outTable)): arcpy.Delete_management(outTable) arcpy.CreateTable_management(scratchGDB, outTblName) arcpy.AddField_management(outTable, "Name", "TEXT") arcpy.AddField_management(outTable, "Population", "DOUBLE") bList=[] pour i dans la plage (number_of_cpus): bList.append([outTblName,chr(65+i),i*i]) pool = multiprocessing.Pool (number_of_cpus) pour i dans pool.map(function, bList): print("Writing") rows=arcpy.da.TableToNumPyArr ay(os.path.join(scratchGDB, outTblName),["NAME", "POPULATION"]) print (rows)

m'a donné cette sortie:

Cela fonctionne comme prévu.


SELECT et UPDATE simultanés en python multitraitement

La requête SQL et le code Python utilisés pour faire correspondre les lignes peuvent être trouvés sur https://github.com/boerngen-schmidt/commuter-simulation/blob/master/code/builder/process_point_mass_matcher.py (je ne le publierai pas ici en raison à sa longueur). Mais en gros ce que je fais c'est :

  1. SELECT lignes, ordonnées au hasard à partir de la table des points de départ
  2. JOINDRE les lignes, ordonnées au hasard à partir de la table des points de destination
  3. Prenez le résultat, parcourez-le et mettez à jour les points dans la table de départ et de destination comme utilisé
  4. Enregistrer le résultat dans une autre table (fait par un autre thread)

Lorsque j'utilisais plusieurs processus avec SELECT . FOR UPDATE J'ai rencontré des blocages (actuellement, je n'utilise qu'un seul processus, donc l'instruction FOR UPDATE est actuellement omise). Jusqu'à présent, j'ai lu un peu sur les mécanismes de verrouillage SERIALIZABLE et ainsi de suite, mais je ne parviens pas à les saisir pleinement.

Est-il possible de rendre compatible le multitraitement correspondant ? A quoi ressembleraient les déclarations ?


La gestion du serveur et de la connexion à la base de données à l'aide de dictionnaires avec des valeurs qui ne sont pas censées être modifiées semble moche. A la place, je m'appuierais sur :

  1. Capacité de Tornado à récupérer l'IOLoop créé à l'aide de IOLoop.current()
  2. La possibilité de créer un objet d'application personnalisé qui est disponible pour chaque gestionnaire pour stocker des objets spécifiques à l'application tels que la connexion à la base de données.

L'utilisation de paramètres par défaut pour certaines fonctions peut également aider à simplifier les choses.

Enfin, vous devez utiliser des chemins absolus plutôt que relatifs au répertoire courant.

Je changerais certains des éléments en quelque chose du genre:

Je vous laisse découvrir le reste.


3 réponses 3

Ce n'est pas le code spécifique dont vous avez besoin, juste une démonstration de la façon de travailler avec BeautifulSoup. Il trouve la table dont l'identifiant est "Table1" et obtient tous ses éléments tr.

Voici un exemple de travail pour un <table> générique . (Bien que vous n'utilisiez pas votre page en raison de l'exécution de javascript nécessaire pour charger les données de la table)

Extraire les données du tableau d'ici PIB (Produit Intérieur Brut) par pays.

Ci-dessous, la fonction analyse un segment html commencé par la balise <table> suivi de plusieurs balises <tr> (lignes de tableau) et internes <td> (données de table). Il renvoie une liste de lignes avec des colonnes internes. Accepte un seul <th> (en-tête/données de table) dans la première ligne.


Échec CUDA de stacktrace multitraitement Python 3 ?

Je travaille sur un script de traitement de données et j'essaie d'utiliser le multitraitement pour qu'il s'exécute plus rapidement. Chaque fois que j'exécute le script python, j'obtiens l'erreur suivante :

2020-12-24 18:30:22.679414457 [E:onnxruntime:, séquentiel_executor.cc:165 Execute] Code d'état différent de zéro renvoyé lors de l'exécution du nœud ArgMax. Nom : 'ArgMax' Message d'état : /onnxruntime_src/onnxruntime/core/providers/cuda/cuda_call.cc:97 bool onnxruntime::CudaCall(ERRTYPE, const char*, const char*, ERRTYPE, const char*) [avec ERRTYPE = cudaError bool THRW = true] /onnxruntime_src/onnxruntime/core/providers/cuda/cuda_call.cc:91 bool onnxruntime::CudaCall(ERRTYPE, const char*, const char*, ERRTYPE, const char*) [avec ERRTYPE = cudaError THRW = vrai] Échec CUDA 2 : manque de mémoire GPU=0 nom d'hôte=- expr=cudaMalloc((void**)&p, size)

Il semble que l'erreur manque de mémoire, mais je suis assez confus quant à la façon dont cela pourrait être le cas car je n'utilise que 5 processus et j'ai déjà utilisé 5 à 10 avec d'autres scripts sur le même ordinateur. Je suis assez nouveau dans le multitraitement et pas le meilleur en Python, alors est-ce que quelqu'un a une idée sur la façon de résoudre ce problème ? Je ne suis pas en mesure de fournir le code pour le moment (mais je peux le fournir sous peu si nécessaire).


1 réponse 1

Étant donné que vous exigez déjà que le nom de fichier commence par le nom de lecteur correct, votre cible ressemblera déjà à un chemin valide normal. Vous pouvez donc au moins vérifier si ce que l'utilisateur a entré est réellement le bon chemin, court-circuitant ainsi toute la recherche :

Vous devez également arrêter de chercher dès que vous avez trouvé votre cible et utiliser le mot-clé in au lieu de vérifier manuellement tous les fichiers vous-même :

A part ça, je crains que vous n'ayez surtout pas de chance. Il n'y a que deux façons de trouver rapidement quelque chose dans un gros tas de quelque chose :

  1. Vous recherchez dans toutes les choses jusqu'à ce que vous trouviez ce que vous cherchez.
  2. Vous avez une structure de données, appelée un index, qui vous indique comment trouver chacun (ou au moins certains, y compris, espérons-le, celui que vous recherchez) des quelque chose.

Dans le monde Unix, il existe l'outil de ligne de commande locate , qui utilise une base de données de fichiers régulièrement mise à jour pour accélérer la recherche de fichiers (tant qu'ils se trouvent dans cette base de données). Je ne sais pas quel est l'outil Windows équivalent (ligne de commande), bien que vous puissiez trouver une solution ici. Vous pouvez ensuite appeler cet outil à l'aide de subprocess .

De votre côté, si vous avez besoin de cette recherche très souvent (deux fois c'est probablement déjà assez souvent), vous pouvez également créer un tel index vous-même, ce qui signifie que vous n'avez à vérifier tous les fichiers qu'une seule fois :


Détails

@J.D a demandé à juste titre plus de détails. Je ne suis autorisé à partager qu'un montant limité :

La table temporaire fournissant l'entrée a différentes colonnes pour les noms réels, de naissance et de mère pour différentes personnes.

J'ai également une trame de données dans le script externe contenant des prénoms valides et des genres associés analysés à partir d'un JSON qui est passé en tant que nvarchar(max). Cette méthode décrite ici.

Mon script extrait les titres, les noms de famille, les prénoms et devine le sexe biologique et le statut martial. Les noms ne sont pas des noms anglais.

J'applique une fonction au premier axe de l'entrée Pandas Dataframe qui effectue l'extraction.

J'utilise uniquement les méthodes fournies par Pandas.

Avec un environnement python standard, j'utiliserais la fonction np.array_split pour diviser la trame de données et utiliserais le module de multitraitement pour appliquer la fonction d'extraction sur les divisions dans les processus parallèles, puis concaténer les trames de données. Comme vous pouvez le voir, il s'agit d'un problème de traitement de texte et ne peut pas être vectorisé comme un mathématique pourrait l'être. Des outils comme Dask ne peuvent donc pas être utilisés ici.


Comment appeler les lectures d'un script qui lit un capteur à utiliser par un autre script qui contrôle les servos

J'essaie d'utiliser les lectures de l'accéléromètre d'un IMU MPU9250 pour contrôler les servos. Pour cela, j'ai créé (avec l'aide de ressources en ligne) un script (IMUmodule) qui lit l'IMU et crache l'accélération de X = AccXangle et Y = AccYangle.

Si j'exécute le script IMU, je peux imprimer X et Y sans problème. X et Y sont mis à jour toutes les 0,1 secondes.

Mais si je crée un autre script, cela importe le module IMU et essaie d'imprimer les valeurs X et Y se bloque ou dit que IMUmodule n'a pas d'attribut appelé AccXangle. (ce que je suis sûr qu'il a)

Voici le code qui crache X et Y, autrement appelé IMUmodule.py :

Comme test, j'ai fait un code de test pour m'assurer que je pouvais importer x et y :

Mais il dit qu'IMUmodlue n'a pas d'attribut appelé AccXangle.

Je suis nouveau sur Python et tout ce qui concerne RPI, veuillez donc pardonner mon ignorance.

Merci. Bravo à OZZMAKER pour avoir créé presque tout le code ci-dessus.

J'ajoute ici le code que j'ai créé pour déplacer les servos manuellement. Je souhaite utiliser les mesures de IMUmodule (AccXangle et AccYangle) pour créer des conditions permettant de déplacer les servos.


1.7. Extraction de paramètres dans les fonctions d'extension¶

La fonction PyArg_ParseTuple() est déclarée comme suit :

Le argument argument doit être un objet tuple contenant une liste d'arguments transmise de Python à une fonction C. Le format argument doit être une chaîne de format, dont la syntaxe est expliquée dans Parsing arguments and building values ​​dans le Python/C API Reference Manual. Les arguments restants doivent être des adresses de variables dont le type est déterminé par la chaîne de format.

Notez que bien que PyArg_ParseTuple() vérifie que les arguments Python ont les types requis, il ne peut pas vérifier la validité des adresses des variables C passées à l'appel : si vous faites des erreurs là-bas, votre code plantera probablement ou au moins écrasera des bits aléatoires dans Mémoire. Donc sois prudent!

Notez que toutes les références d'objet Python fournies à l'appelant sont emprunté les références ne décrémentent pas leur nombre de références !


En détail

Python est un langage de programmation dynamique. Il est connu pour sa grande lisibilité et c'est donc souvent le premier langage appris par les nouveaux programmeurs. Python étant multi-paradigme, il peut être utilisé pour réaliser la même chose de différentes manières et il est compatible sur différentes plates-formes. Même si vous trouvez facile d'écrire du code Python, écrire du code efficace, facile à entretenir et à réutiliser n'est pas si simple.

Ce livre est un guide faisant autorité qui vous aidera à apprendre de nouvelles méthodes avancées de manière claire et contextualisée. Il commence par créer un environnement spécifique au projet à l'aide de venv, vous présentant différentes syntaxes Pythonic et les pièges courants avant de passer aux fonctionnalités fonctionnelles de Python. Il explique comment créer différents décorateurs, générateurs et métaclasses. Il vous présente également functools.wraps et coroutines et leur fonctionnement. Plus tard, vous apprendrez à utiliser le module asyncio pour les clients et serveurs asynchrones. Vous vous familiariserez également avec différents systèmes de test tels que py.test, doctest et unittest, ainsi qu'avec des outils de débogage tels que le débogueur et le gestionnaire de pannes Python. Vous apprendrez à optimiser les performances des applications afin qu'elles fonctionnent efficacement sur plusieurs machines et versions de Python. Enfin, il vous apprendra comment accéder aux fonctions C avec un simple appel Python. À la fin du livre, vous serez capable d'écrire des scripts plus avancés et de relever des défis plus importants.