Compilation de scripts Python (en .exe) utilisant les outils de géotraitement ArcGIS?

12

Je code avec Python depuis plusieurs mois maintenant et j'ai développé des scripts assez complexes pour des tâches principalement de géotraitement. Cela étant dit, j'apprends encore beaucoup car je viens d'un arrière-plan SQL / VBA / VBScript.

Je sais que le code compilé s'exécute généralement plus rapidement que le code qui doit être traité par un interpréteur de langage, donc je suis intéressé par la possibilité de compiler un script Python de géotraitement dans un fichier .EXE pour travailler avec des données volumineuses.

Est-ce seulement possible? Si tel est le cas, quelle est la meilleure façon de compiler un script Python (.py) qui importe les modules arcgisscripting ou arcpy?

J'ai passé quelques minutes à essayer de trouver ce que je voulais faire et la recherche a renvoyé cet article entre autres: http://www.ehow.com/how_2091641_compile-python-code.html

Le compilateur semblait fonctionner, mais lors de l'exécution du fichier .EXE résultant, il a donné une erreur cryptique indiquant que certains fichiers n'étaient pas disponibles.

Le script Python exécute ce qui semble être assez bien à partir de la ligne de commande, mais je me demande si je pourrais voir une légère amélioration si je pouvais compiler le fichier .py. Encore une fois, je travaille avec des ensembles de données volumineux qui prennent plus de 20 heures à traiter (délimiter les bassins versants des sites d'échantillonnage de la qualité de l'eau). Je vais prendre tout ce que je peux pour améliorer.

Le script s'est exécuté 10% plus rapidement en dehors d'ArcGIS à partir de la ligne de commande à l'aide d'un ensemble de sites de test par rapport à la configuration du script en tant qu'outil de script dans une nouvelle boîte à outils dans ArcCatalog. J'ai exécuté le script à partir de la ligne de commande sans aucune instance d'ArcGIS ouverte sur une machine dédiée.

Alors, est-il possible de compiler des scripts Python qui importent le module arcgisscripting et qui appellent les outils ArcToolBox?

ÉDITER

Merci pour la contribution, cela m'a été utile. Le script est en grande partie un moyen de coordonner un certain nombre d'outils ArcGIS et de produire dans les formats / emplacements souhaités / avec l'attribution appropriée. J'ai déjà coupé du gras en écrivant dans un dossier de travail au lieu d'une géodatabase personnelle de travail pour certains fichiers raster intermédiaires afin qu'ils puissent être stockés au format ESRI GRID par rapport au format IMG. Je vais cependant consulter les suggestions du profileur.

Il y en a dans mon bureau qui remettent en question Python disant "que le code compilé est tellement plus rapide que le code passant par un interpréteur" principalement en comparaison, disons, avec un programme Visual Basic compilé ou un programme VB.NET, mais c'est un bon point que les outils vont prendre du temps de toute façon. Et, il semble qu'avec les machines informatiques actuelles, le code interprété ne soit pas beaucoup plus lent que le code compilé pour justifier d'aller plus loin.

EDIT - mise à jour sur l'optimisation du programme avec des formats raster.

Je voulais suivre mon "optimisation" de ce programme Python, et j'ai pu gagner 2 heures de temps de traitement en écrivant des rasters intérimaires au format GRID au lieu d'une géodatabase personnelle. Non seulement cela, il y a eu une réduction SIGNIFICATIVE de la consommation d'espace disque de la taille des données. L'exécution d'origine que j'ai faite pour écrire tous les rasters (et ce n'étaient que des entités ponctuelles converties en rasters, puis des rasters de bassin versant) a donné 37,1 Go de données uniquement pour ces fichiers. L'écriture des deux dernières sorties de données dans un dossier au format GRID a été réduite à 667 Mo de données.

Je serais curieux de voir comment un fichier GDB gérerait ces données, mais principalement en fonction de la taille des données. Mais, réduire mon temps de traitement de 9,5 heures à 7,5 heures est certainement suffisant pour plaider en faveur du traitement des rasters en dehors des géodatabases au format GRID.

turc
la source
Ce matin, le blog ArcGIS Server arrive à point nommé. Sterling @ esri fait un bon travail pour expliquer pourquoi et quand [ici.] [1] [1]: blogs.esri.com/Dev/blogs/arcgisserver/archive/2011/04/12/…
Brad Nesom

Réponses:

15

Première question: combien de choses faites-vous en Python? Faites-vous simplement appel à des outils de géotraitement ou effectuez-vous une quantité importante d'analyse numérique en Python? Si le premier, les goulots d'étranglement vivent probablement dans les outils et l'utilisation de code natif dans votre script ne vous achètera pas autant que d'autres solutions de contournement intelligentes. Dans ce dernier cas, vous voudrez peut-être trouver ce qui est lent et le rendre plus rapide avec de meilleurs algorithmes, ou éventuellement numpy, ou une autre option, comme indiqué ci-dessous.

py2exe ne compile pas réellement votre code en x86 / x64 natif, il fournit simplement un exécutable qui incorpore votre script en bytecode et fournit un moyen principalement portable de le distribuer aux utilisateurs sans Python sur leurs systèmes. Il a échoué lors de la tentative de regroupement de l'arggisscripting, c'est pourquoi cela n'a pas fonctionné. En fait, py2exe ne fonctionnera toujours pas en termes de performances.

Je vous recommande fortement d'utiliser d'abord un profileur pour identifier les bits lents et optimiser à partir de là. Il existe un très bon ensemble intégré à Python , utilisez cProfile à long terme pour trouver des endroits potentiels pour le rendre plus rapide. De là, vous pouvez optimiser les sections à l'extérieur en C personnalisé ou éventuellement expérimenter avec de petites portions comme modules Cython .pyx.

Vous pouvez regarder dans Cython pour éventuellement construire l'intégralité du script Python en tant que module d'extension de code natif, mais Psyco peut également vous donner une amélioration des performances avec une barrière inférieure à l'entrée.

Jason Scheirer
la source
4

Combien de temps la délimitation du bassin versant prend-elle si elle est exécutée à partir des outils standard d'ArcToolbox par rapport à la version de script? Si les temps sont similaires, je soupçonne qu'il n'y aura aucune amélioration. Vous souhaiterez peut-être envisager d'exécuter de longs processus en arrière-plan en dehors d'ArcMap.


la source
J'ai clarifié ma question d'origine et j'espère toujours obtenir une réponse affirmative oui / non s'il est possible de compiler un tel code car cette réponse ne répond pas à ma question.
turkishgold
2
@turkish Il ne répond peut-être pas directement à votre question, mais c'est une excellente suggestion. Il y a de fortes chances que votre processus passe tout son temps à la délimitation, donc aucune modification du code ne vous sera utile. Cependant, reconsidérer l' algorithme pourrait faire une énorme différence. Donc, l'une des premières choses que vous voulez faire est de profiler l'exécution en cours pour voir si vous perdez votre temps avec cette approche de compilation.
whuber
1
Je suis d'accord avec @Dan et @whuber. Je pense que faire une analyse plus approfondie (c.-à-d. L'analyse comparative et le profilage) donnera une bien meilleure idée des améliorations des performances qu'une simple approche de compilation par force brute.
Jason Scheirer
4

N'utilisez pas de géodatabase personnelle sans raison valable. D'après notre expérience, ils sont constamment beaucoup plus lents que toutes les autres formes de stockage de données esri ( réf ). Bien que j'aie lu un rapport ici sur GIS.se qui a vu un personnel plus rapide que le fichier gdb.

Lorsque le flux de travail se compose de nombreuses petites itérations, l'appel pour créer le géoprocesseur et extraire une licence est souvent la partie la plus coûteuse en temps d'utilisation de python. Donc, faire autant que possible devant ou derrière gp = ...(ou import arcpyen v10) est une technique que j'utilise beaucoup.

En ce qui concerne la compilation, cette citation le dit le mieux:

Il convient de noter que lors de l'exécution d'un script [python] compilé a un temps de démarrage plus rapide (car il n'a pas besoin d'être compilé), il ne s'exécute pas plus rapidement.

Mark Cederholm a une présentation sur l'utilisation d' ArcObjects en Python avec quelques statistiques sur les opérations de forme (diapositive # 4). Python ne fonctionne pas très bien, fonctionnant à 32% de ce qui peut être réalisé avec C ++ (VBA était de 92%, VB & C # à 48%). N'allez pas courir et crier trop vite, de nombreux outils de géotraitement sont de toute façon des scripts python (recherchez c: \ program files \ arcgis \ pour '* .py').

Comme beaucoup l'ont dit dans d'autres lieux, avec python, le temps passé à essayer d'optimiser les performances en compilant ou en écrivant une fonction de base C ou C ++ éclipse souvent tous les gains de performances réels (éventuellement) réalisés au moment de l'exécution. Beaucoup disent que le principal avantage de Python est l'optimisation et l'amélioration du temps de développement ; l'attention humaine est beaucoup plus précieuse et coûteuse que le temps de traitement de la machine.

Matt Wilkie
la source
1
Oui à tous points de vue. Pour mon argent, l'utilisation optimale du temps de développement consiste à prototyper * en Python, à comparer, à dérouler en C / C ++ pour optimiser les goulots d'étranglement. * Je dis prototype, mais je sais que 95% du temps ce «prototype» va être mis en production.
Jason Scheirer
Grands commentaires et merci pour les liens sur ArcObjects en Python. Je pense que l'écriture dans un GDB présente des avantages du point de vue de la gestion des données par rapport au fichier de formes (restrictions des tables d'attributs dans les fichiers de formes par rapport aux classes d'entités, représentation géométrique, pratiques générales de gestion des données, etc.) ainsi que des choses que vous pouvez faire beaucoup plus facilement et plus proprement. un environnement Access vs traiter avec des fichiers DBF. Donc, essentiellement un compromis coût-avantage avec ce que vous faites et ce que vous allez avoir à faire avec les données de sortie. Le juste milieu des rasters en dehors de GDB et tout le reste dans GDB semble fonctionner.
turkishgold
1

Vous ne pouvez pas compiler du code python en code machine. Lorsqu'il s'exécute pour la première fois, il est compilé en «bytecode», un langage intermédiaire (qui crée des fichiers pyc)

py2exe encapsule les fichiers dll requis par l'interpréteur et tous les fichiers python / fichiers externes requis dans un exécutable. Il n'est pas compilé - l'exécution ne devrait pas être très différente.

Il est possible de faire fonctionner le code Python très rapidement, en utilisant une combinaison de différentes techniques.

La première chose à faire est de profiler votre code pour trouver les goulots d'étranglement. Une fois trouvé, j'utilise généralement ce processus:

  • Éliminez les boucles «for» en utilisant des tableaux numpy ou la fonction map (). Cela pousse essentiellement la boucle en C.
  • Enquêter sur de meilleures implémentations de l'algorithme (ce type va simultanément avec ce qui précède). Des choses comme réduire le nombre d'opérations d'E / S, assurer que les données sont accessibles / stockées dans des blocs contigus.
  • Interpréter les «astuces» comme éviter les recherches coûteuses dans les boucles, éviter les blocages «if» dans les boucles (utilisez plutôt «try»)
  • Profil à nouveau
  • S'il est encore trop lent, essayez de pousser les parties critiques en C à l'aide de Cython (ou d'écrire directement en C, de créer une DLL et d'utiliser des ctypes pour l'appeler)
  • Profil à nouveau
  • Si c'est encore trop lent, regardez l'informatique parallèle ou GPU (bibliothèque multiprocessing, pyCUDA, ParallelPython etc)
James
la source
0

Si vous importez un script python depuis un autre emplacement, il génère un fichier .pyc. Ainsi, un moyen simple de tester si la compilation fait une différence serait de transformer votre script en fonction (par exemple main ()). Si vous enregistrez ce script sous, example.pycréez un autre fichier avec les lignes suivantes:

import example
example.main() # call your script(s)

Si vous exécutez à partir du script et que vous l'exécutez lorsqu'il est importé, vous pouvez peut-être voir quelle est la différence. C'est une façon low-tech de le faire.

djq
la source