Suite

Débogage RuntimeError : espace de travail déjà en mode transaction à partir des classes d'entités arcpy.da.UpdateCursor et ArcSDE ?


Je fais ma première tentative de modification d'une classe d'entités ArcSDE avec python via un da.UpdateCursor. Je prends essentiellement le code que j'ai écrit pour une classe d'entités de géodatabase fichier et je l'applique à une classe d'entités SDE. Cela produit une erreur et je ne sais pas comment résoudre le problème.

J'utilise ArcGIS 10.1 for Desktop.

Code pertinent :

Struxfeature = r"DatabaseConnectionsPipelinePathways.sdePPGIS.StruxPPGIS.StruxPts_v04_all" P6feature = r"DatabaseConnectionsPipelinePathways.sdePPGIS.StruxPPGIS.Land_Projects_Parcelsways_P6" SDE ConnectionsR"DatabasePathways.sdePPGIS.StruxPPGIS.Land_Projects_Parcelsways_P6" E1B8" Parent = "SDE.DEFAULT" version = "change_RW_VC_4447_14_to_C" #Create Version print "Creating version" arcpy.CreateVersion_management(SDE, Parent, version, "PUBLIC") VersionName = UserID.upper() + "." + version #Layers arcpy.MakeFeatureLayer_management (Struxfeature, "Struxlyr") arcpy.MakeFeatureLayer_management (P6feature, "P6lyr") #Passer à la version print "Switching version" arcpy.ChangeVersion_management("Struxlyr", "TRANSACTIONAL", VersionName) arcpy.ChangeVersion_management ("P6lyr", "TRANSACTIONAL", VersionName) #Démarrer l'édition print "Initiation de l'édition" edit = arcpy.da.Editor(SDE) edit.startEditing() # Commencer une opération d'édition edit.startOperation() #Modifier les numéros de projet P6 print "Mise à jour de P6.
" P6Cursor = arcpy.da.UpdateCursor ("P6lyr", ["P6_NBR", "Name"]) pour la ligne dans P6Cursor : codecodecode

L'erreur vient de la ligne 'for row in P6Cursor:'

Traceback (appel le plus récent en dernier) : Fichier "C:E1B8ScriptTestingScriptsIUseChangeP6.py", ligne 81, dans  pour la ligne dans P6Cursor : RuntimeError : espace de travail déjà en mode transaction

Avec de l'aide, j'ai trouvé ma solution, bien que le raisonnement qui la sous-tend soit actuellement un peu flou. Dans mon code, créer une version via un fichier de connexion SDE, puis créer la couche d'entités à modifier via un autre fichier de connexion SDE connecté à la nouvelle version fonctionne. De plus, edit.startEditing doit avoir la variable 'multiuser_mode' définie sur true (valeur par défaut). Si je comprends bien, cette variable indique s'il peut y avoir plusieurs versions/utilisateurs autorisés pour la couche. Étant donné que cela est toujours vrai pour une couche d'entités SDE, la définition de cette variable sur False provoque une erreur.

Code de fonctionnement, où je teste un curseur de mise à jour :

import arcpy import os #Locals P6featureName = r"PPGIS.StruxPPGIS.Land_Projects_Parcels_P6" Parent = "SDE.DEFAULT" version = "SDE_Test" Server = *** Service = *** user = *** Pass = *** SDE = "Database ConnectionsPipelinePathways.sde" temploc = r"C:E1B8ScriptTestingWorkspace" fil = "SDETempConn" env.overwriteOutput = True #Create Version print "Création de la version" arcpy.CreateVersion_management (SDE, Parent, version , "PUBLIC") NomVersion = user.upper() + "." + version #Create new connection workspace = os.path.join (temploc, fil + ".sde") print "Creating SDE connection" arcpy.CreateArcSDEConnectionFile_management (temploc, fil, Server, Service, username = user, password = Pass, version = VersionName) #Layers P6feature = os.path.join (workspace, P6featureName) arcpy.MakeFeatureLayer_management (P6feature, "P6lyr") #Commencer l'édition print "Initiation de l'édition" edit = arcpy.da.Editor (workspace) edit.startEditing () edit.startOperation() #Test Cursor print "Test du curseur" P6Cursor = arcpy.da.UpdateCursor ("P6lyr", ["NAME"]) pour la ligne dans P6Cursor : print row[0] del row del P6Cursor #Stop/save edits edit.stopOperation() print "Arrêter l'édition" edit.stopEditing("True") #Passer à la version print "Changement de version" arcpy.ChangeVersion_management("P6lyr", "TRANSACTIONAL", Parent) #Réconcilier et poster print "Réconcilier et publier " arcpy.ReconcileVersions_management (workspace, "", Parent, VersionName, with_post = "POST", with_delete = "DELETE_VERSION")

Merci à Ben Nadler pour l'aide.


Dans mon cas, la table dans laquelle nous étions en train d'insérer n'était pas enregistrée dans la géodatabase et n'allait jamais être enregistrée. L'ajout d'une clé primaire et d'une colonne d'identité a résolu ce problème pour nous.


J'ai rencontré le même problème : "espace de travail déjà en mode transaction". J'avais une base de données Microsoft SQL Server connectée à ArcCatalog en tant que SDE.

Et la décision dans mon cas était simplement de changer le type de colonne "timestamp" de la table cible en "image".


J'ai également eu cette erreur dans mon script python lors de l'ajout de nouvelles couches de fonctionnalités. Après avoir perdu beaucoup de temps, j'ai pensé que les calques n'étaient pas enregistrés. J'ai donc enregistré les couches et je l'ai fait fonctionner.


Mieux vaut utiliser Python ou R pour rechercher des enregistrements dans une très grande table pour les fonctionnalités correspondantes dans FGDB ?

EDIT : j'essaie de trouver la meilleure solution, et bien que je ne connaisse que Python, ce que j'essaie de faire ne devrait pas être si difficile ou prendre autant de temps. J'ai modifié le titre pour poser des questions sur les options utilisant R ou d'autres programmes.

Je travaille sur le défi suivant dans ArcGIS 10.1 sur un ordinateur 64 bits avec Python 2.7.

J'ai une table avec trois champs : ID#, "Revenue" et "Live" - et 2,1 millions d'enregistrements.

J'essaie d'extraire des classes d'entités d'un fGDB en faisant correspondre son nom avec le numéro d'identification dans cette table, en ajoutant deux champs au FC et en remplissant ces champs avec la valeur des données Revenue et Live.

Mon script comprend des couches et des couches de boucles for, d'instructions if et de curseurs de recherche. Bien que cela ait fonctionné dans un petit lot de test, cela prend une éternité avec les données réelles, car il recherche 2,1 millions d'enregistrements.

J'ai inclus mon script ci-dessous, qui fonctionne - et montre également mon flux logique, c'est là que j'ai besoin de conseils.

Quelle est la meilleure stratégie pour comparer/faire correspondre une très longue liste d'enregistrements à un ensemble de classes d'entités ?


Vjylku

Comment résoudre une équation différentielle avec un terme à une puissance ?

Quel tube conviendra à une roue -(700 x 25c) ?

Rendre les éclipses solaires extrêmement rares, mais avoir toujours de nouvelles lunes

Puis-je équiper Crâneclamp sur une créature que je sacrifie ?

Somme non déterministe des flottants

Pourquoi suis-je autorisé à créer plusieurs pointeurs uniques à partir d'un seul objet ?

Si/quand le Royaume-Uni quitte l'UE, un futur gouvernement peut-il organiser un référendum pour rejoindre l'UE ?

Différents changements harmoniques impliqués par une simple gamme décroissante

Si le tas est initialisé pour la sécurité, alors pourquoi la pile n'est-elle pas initialisée ?

Pourquoi la notation standard ne préserve-t-elle pas les intervalles (visuellement)

Comment éviter les superviseurs aux opinions préjugées ?

Pourquoi Khan n'a-t-il pas été ressuscité lors de l'explosion de Genesis ?

Qu'est-ce que ( CFMCC ) sur la carte d'approche ILS?

« pour avoir causé l'autisme dans X » est-il grammatical ?

HostGator stocke-t-il mon mot de passe en clair ?

Magie peu fiable - Est-ce que ça vaut le coup ?

Existe-t-il un analogue des espaces projectifs pour des schémas appropriés ?

Pouvez-vous remplacer un sort mineur de trait racial lorsque vous montez de niveau ?

Créer un nouveau champ dans un fichier de formes à l'aide d'ArcPy ?

Je suis nouveau dans les scripts et dans Python/arcpy. Mon intention avec ce script est de :


  • sélectionnez des points d'une classe d'entités qui se trouvent dans un polygone cible et qui répondent à une requête attributaire spécifiée par la variable « agréments ».
  • créer trois nouvelles classes d'entités de ces points.
  • ajouter un nouveau champ de texte à chacune des classes d'entités.
  • mettre à jour ce champ.

Je suis bloqué à l'étape où j'ajouterais le nouveau champ à chaque nouvelle classe d'entités et mettrais à jour le curseur.

curseur.updateRow() prend une séquence, mais vous fournissez une valeur unique. Essayez cursor.updateRow([dataSource]) . Si cela ne fonctionne pas après cela, nous aurons besoin du message d'erreur réel que vous supprimez actuellement avec le bloc try/except. C'est généralement une mauvaise pratique d'utiliser des blocs try/except "nus", car cela masque toute erreur réelle qui se produit, que ce soit ou non une erreur à laquelle vous vous attendez, et ces retraçages sont essentiels pour le débogage.

Je suis nouveau dans les scripts et dans Python/arcpy. Mon intention avec ce script est de :


  • sélectionnez des points d'une classe d'entités qui se trouvent dans un polygone cible et qui répondent à une requête attributaire spécifiée par la variable « agréments ».
  • créer trois nouvelles classes d'entités de ces points.
  • ajouter un nouveau champ de texte à chacune des classes d'entités.
  • mettre à jour ce champ.

Je suis bloqué à l'étape où j'ajouterais le nouveau champ à chaque nouvelle classe d'entités et mettrais à jour le curseur.

curseur.updateRow() prend une séquence, mais vous fournissez une valeur unique. Essayez cursor.updateRow([dataSource]) . Si cela ne fonctionne pas après cela, nous aurons besoin du message d'erreur réel que vous supprimez actuellement avec le bloc try/except. C'est généralement une mauvaise pratique d'utiliser des blocs try/except « nus », car cela masque toute erreur réelle qui se produit, qu'elle soit ou non celle à laquelle vous pourriez vous attendre, et ces retraçages sont essentiels pour le débogage.

Je suis nouveau dans les scripts et dans Python/arcpy. Mon intention avec ce script est de :


  • sélectionnez des points d'une classe d'entités qui se trouvent dans un polygone cible et qui répondent à une requête attributaire spécifiée par la variable « agréments ».
  • créer trois nouvelles classes d'entités de ces points.
  • ajouter un nouveau champ de texte à chacune des classes d'entités.
  • mettre à jour ce champ.

Je suis bloqué à l'étape où j'ajouterais le nouveau champ à chaque nouvelle classe d'entités et mettrais à jour le curseur.

Je suis nouveau dans les scripts et dans Python/arcpy. Mon intention avec ce script est de :


  • sélectionnez des points d'une classe d'entités qui se trouvent dans un polygone cible et qui répondent à une requête attributaire spécifiée par la variable « agréments ».
  • créer trois nouvelles classes d'entités de ces points.
  • ajouter un nouveau champ de texte à chacune des classes d'entités.
  • mettre à jour ce champ.

Je suis bloqué à l'étape où j'ajouterais le nouveau champ à chaque nouvelle classe d'entités et mettrais à jour le curseur.


18 réponses 18

D'après ce dont je me souviens sous Windows, l'ordre de recherche d'une dll est :

  1. Répertoire actuel
  2. Dossier système, C:windowssystem32 ou c:windowsSysWOW64 (pour un processus 32 bits sur une boîte 64 bits).
  3. Lecture à partir de la variable d'environnement Path

De plus, je vérifierais les dépendances de la DLL, le marcheur de dépendances fourni avec Visual Studio peut vous aider ici, il peut également être téléchargé gratuitement : http://www.dependencywalker.com

Vous pouvez utiliser l'outil dumpbin pour connaître les dépendances DLL requises :

Cela vous indiquera quelles DLL votre DLL doit charger. Recherchez particulièrement MSVCR*.dll. J'ai vu votre code d'erreur se produire lorsque le redistribuable Visual C++ correct n'est pas installé.

Vous pouvez obtenir les « Packages redistribuables Visual C++ pour Visual Studio 2013 » sur le site Web de Microsoft. Il installe c:windowssystem32MSVCR120.dll

Dans le nom du fichier, 120 = 12.0 = Visual Studio 2013.

Veillez à disposer de la bonne version de Visual Studio (10.0 = VS 10, 11 = VS 2012, 12.0 = VS 2013. ) de la bonne architecture (x64 ou x86) pour la plate-forme cible de votre DLL, et vous devez également faire attention aux versions de débogage . La version de débogage d'une DLL dépend de MSVCR120d.dll qui est une version de débogage de la bibliothèque, qui est installée avec Visual Studio mais pas par le package redistribuable.

C'est un 'kludge' mais vous pouvez au moins l'utiliser pour tester l'intégrité : essayez de coder en dur le chemin d'accès à la DLL dans votre code

Cela dit, dans mon cas, exécutez dumpbin / DEPENDENTS comme suggéré par @anthony-hayward et copiez 32 bits les versions des DLL répertoriées dans mon répertoire de travail ont résolu ce problème pour moi.

Le message est juste un peu trompeur, car ce n'est pas "ma" dll qui ne peut pas être chargée - ce sont les dépendances

La DLL doit être dans le dossier bin.

Dans Visual Studio, j'ajoute la dll à mon projet PAS dans les références, mais "Ajouter un fichier existant". Définissez ensuite la propriété "Copy to Output Directory" pour la dll sur "Copy if newer".

Essayez d'entrer le chemin complet de la dll. Si cela ne fonctionne pas, essayez de copier la dll dans le dossier system32.

Assurez-vous que toutes les dépendances de votre propre dll sont présentes à proximité de la dll ou dans System32 .

Activez la journalisation de fusion, consultez cette question pour obtenir de nombreux conseils sur la façon de procéder. Le débogage des problèmes de chargement des applications en mode mixte peut être une vraie douleur royale. La journalisation de fusion peut être d'une grande aide.

Il y a une chose très amusante (et qui a une pertinence technique) qui pourrait vous faire perdre des heures, alors pensez à la partager ici -

J'ai créé un projet d'application console ConsoleApplication1 et un projet de bibliothèque de classes ClassLibrary1 .

Tout le code qui faisait le p/invoke était présent dans ClassLibrary1.dll . Ainsi, avant de déboguer l'application à partir de Visual Studio, j'ai simplement copié l'assembly non géré C++ ( myUnmanagedFunctions.dll ) dans le répertoire indebug du projet ClassLibrary1 afin qu'il puisse être chargé au moment de l'exécution par le CLR.

erreur pendant des heures. Plus tard, j'ai réalisé que tous ces assemblys non gérés qui doivent être chargés doivent être copiés dans le répertoire indebug du projet de démarrage ConsoleApplication1 qui est généralement un formulaire win, une console ou une application Web.

Soyez donc prudent, le répertoire actuel dans la réponse acceptée signifie en fait le répertoire actuel de l'exécutable principal à partir duquel votre processus de candidature commence. Cela semble évident, mais ce n'est peut-être pas le cas parfois.

Leçon apprise - Placez toujours les dll non gérées dans le même répertoire que l'exécutable de démarrage pour vous assurer qu'il peut être trouvé.