如果从 C# 控制台应用程序调用,则调用的 Arcpy 脚本不会完成
Posted
技术标签:
【中文标题】如果从 C# 控制台应用程序调用,则调用的 Arcpy 脚本不会完成【英文标题】:Called Arcpy Script doesn't finish if called from C# Console App 【发布时间】:2021-12-01 16:36:59 【问题描述】:早安 ***ers,
如果没有您的帮助,我无法解决另一个问题。我正在开发一个 C# 控制台应用程序 (.NET 5),它调用不同的 Python 脚本来执行 ArcGis 内容 (=> "arcpy"-Lib :)。打电话给他们的方案总是一样的,从来没有问题。在渗透测试过程中,我发现其中一个脚本存在问题:
以下脚本“搜索”要素类中的每一行,放大到它并将其导出为 .png 文件。
通过 cmd(非管理员和管理员)或通过 Python Gui(可通过 ArcGis 设置获得)执行此操作,它可以完美运行(=> 创建 138 个图像),但是如果我通过 C# 应用程序执行它,它只会创建 36 个图像,之后,该过程继续运行但不创建图像。创建第 36 张图像后,CPU 使用率从 12% 下降到 0%。
第二个代码 sn-p 显示了被调用的方法,但也描述了调用我的 python 脚本的方案。我非常清楚这写得不好,我会在解决这个问题后做一些代码润色:)
希望有人给点小费。
提前非常感谢您。 亲切的问候, 一月
import arcpy,os, logging
logging.basicConfig(filename='appPython.log', format='%(asctime)s - %(message)s', level=logging.INFO)
#Static Variables
mxdfileName = "D:\DigitalesFahrtenbuch_Datenpunkte\Templates\TemplateTelematik.mxd"
# Set the workspace for ListFeatureClasses
arcpy.env.workspace = str(sys.argv[1])
#arcpy.env.workspace = r"D:\DigitalesFahrtenbuch_Datenpunkte\DigFahrtenbuch_Datenpunkte.gdb"
featureclasses = arcpy.ListFeatureClasses()
try:
# Copy shapefiles to a file geodatabase
for fc in featureclasses:
featureName = os.path.splitext(fc)[0]
if "Dienstverrichtung_" in featureName and "_Projection" in featureName:
print(featureName)
#Global Variables
mxd = arcpy.mapping.MapDocument(mxdfileName)
df = arcpy.mapping.ListDataFrames(mxd,"*")[0]
#Create FeatureLayer
SelectionLayer = arcpy.management.MakeFeatureLayer(fc, "SelectionLayer").getOutput(0)
#Add Layer to mxd
arcpy.mapping.AddLayer(df, SelectionLayer, "TOP")
#Refresh TOC and DataFrames
arcpy.RefreshActiveView()
arcpy.RefreshTOC()
df = arcpy.mapping.ListDataFrames(mxd,"*")[0]
#Refresh TOC and DataFrames
arcpy.RefreshActiveView()
arcpy.RefreshTOC()
df = arcpy.mapping.ListDataFrames(mxd,"*")[0]
feature = arcpy.mapping.ListLayers(mxd, SelectionLayer, df)[0]
fields = ['OID@', 'SHAPE@', 'Name']
pngPath = r"D:\DigitalesFahrtenbuch_Datenpunkte\Images"
with arcpy.da.SearchCursor(feature, fields) as cursor:
for FID, Geometry, Name in cursor:
mxd.title = Name
print(" in Bearbeitung.".format(mxd.title))
query = "ObjectID = ".format(str(FID))
arcpy.management.SelectLayerByAttribute(feature, "NEW_SELECTION", query)
df.zoomToSelectedFeatures()
df.scale=2500
df.referenceScale = 3500
arcpy.RefreshActiveView()
png = "\\.png".format(pngPath, Name)
arcpy.mapping.ExportToPNG(mxd, png, df, df_export_width=2200, df_export_height=1300)
print(" erfolgreich exportiert.".format(mxd.title))
print("Script beendet")
except Exception as e:
logging.error("Exception occurred", exc_info = True)
public static async Task<Tuple<string, bool>> ZoomToSelectedFeatures(string pPathToPythonExe, string pPathGeoDatabase)
Tuple<string, bool> resultTuple = null;
StringBuilder scriptMessageBuilder = new StringBuilder();
string scriptExceptions = string.Empty;
string scriptPrints = string.Empty;
string pythonPath = @"C:/Python27/ArcGIS10.8/python.exe";
try
await Task.Run(delegate
if (pPathToPythonExe != "")
pythonPath = pPathToPythonExe;
ProcessStartInfo start = new ProcessStartInfo();
//python interprater location
start.FileName = pythonPath;
//argument with file name and input parameters
start.Arguments =
$"Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Python_Scripts\\Batch_ZoomToSelectedFeaturesAndExportPNG_2.py")" +
$" pPathGeoDatabase";
start.UseShellExecute = false; // Do not use OS shell
start.CreateNoWindow = true; // We don't need new window
start.RedirectStandardOutput = true; // Any output, generated by application will be redirected back
start.RedirectStandardError = true; // Any error in standard output will be redirected back (for example exceptions)
start.LoadUserProfile = true;
using (Process process = Process.Start(start))
process.WaitForExit();
using (StreamReader reader = process.StandardOutput)
scriptExceptions = process.StandardError.ReadToEnd(); // Here are the exceptions from our Python script
scriptPrints = reader.ReadToEnd(); // Here is the result of StdOut(for example: print "test")
Debug.WriteLine("Batch_ZoomToSelectedFeaturesAndExportPNG_2.py meldet:");
Debug.WriteLine(scriptPrints);
Debug.WriteLine(scriptExceptions);
scriptMessageBuilder.AppendLine(scriptPrints);
scriptMessageBuilder.AppendLine(scriptExceptions);
resultTuple = new Tuple<string, bool>(scriptMessageBuilder.ToString(), true);
);
catch (Exception e)
Debug.WriteLine(e);
Debug.WriteLine(scriptExceptions);
resultTuple = new Tuple<string, bool>(scriptMessageBuilder.ToString(), false);
return resultTuple;
【问题讨论】:
【参考方案1】:我通过将输出从“打印消息”更改为“日志条目”解决了这个问题。现在....老实说,我不知道为什么,该脚本正确地创建了所有图像。在编辑后的脚本下方。
无论如何,谢谢,祝你有愉快的一天!
import arcpy,os,logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG) # process everything, even if everything isn't printed
fh = logging.FileHandler('D:\\appPython.log')
fh.setLevel(logging.DEBUG) # or any level you want
logger.addHandler(fh)
#Define Variables
#Static Variables
mxdfileName = "D:\DigitalesFahrtenbuch_Datenpunkte\Templates\TemplateTelematik.mxd"
# Set the workspace for ListFeatureClasses
arcpy.env.workspace = str(sys.argv[1])
#arcpy.env.workspace = r"D:\DigitalesFahrtenbuch_Datenpunkte\DigFahrtenbuch_Datenpunkte.gdb"
# Use the ListFeatureClasses function to return a list of
# shapefiles.
featureclasses = arcpy.ListFeatureClasses()
try:
# Copy shapefiles to a file geodatabase
for fc in featureclasses:
featureName = os.path.splitext(fc)[0]
if "Dienstverrichtung_" in featureName and "_Projection" in featureName:
logger.info(featureName)
#Global Variables
mxd = arcpy.mapping.MapDocument(mxdfileName)
df = arcpy.mapping.ListDataFrames(mxd,"*")[0]
#Create FeatureLayer
SelectionLayer = arcpy.management.MakeFeatureLayer(fc, "SelectionLayer").getOutput(0)
#Add Layer to mxd
arcpy.mapping.AddLayer(df, SelectionLayer, "TOP")
#Refresh TOC and DataFrames
arcpy.RefreshActiveView()
arcpy.RefreshTOC()
df = arcpy.mapping.ListDataFrames(mxd,"*")[0]
#Refresh TOC and DataFrames
arcpy.RefreshActiveView()
arcpy.RefreshTOC()
df = arcpy.mapping.ListDataFrames(mxd,"*")[0]
feature = arcpy.mapping.ListLayers(mxd, SelectionLayer, df)[0]
fields = ['OID@', 'SHAPE@', 'Name']
pngPath = r"D:\DigitalesFahrtenbuch_Datenpunkte\Images"
with arcpy.da.SearchCursor(feature, fields) as cursor:
for FID, Geometry, Name in cursor:
mxd.title = Name
#print(" in Bearbeitung.".format(mxd.title))
logger.info(" in Bearbeitung.".format(mxd.title))
query = "ObjectID = ".format(str(FID))
arcpy.management.SelectLayerByAttribute(feature, "NEW_SELECTION", query)
df.zoomToSelectedFeatures()
df.scale=2500
df.referenceScale = 3500
arcpy.RefreshActiveView()
png = "\\.png".format(pngPath, Name)
arcpy.mapping.ExportToPNG(mxd, png, df, df_export_width=2200, df_export_height=1300)
logger.info(" erfolgreich exportiert.".format(mxd.title))
#print(" erfolgreich exportiert.".format(mxd.title))
logger.info("Script beendet")
except Exception as e:
logger.error(e)
【讨论】:
以上是关于如果从 C# 控制台应用程序调用,则调用的 Arcpy 脚本不会完成的主要内容,如果未能解决你的问题,请参考以下文章
从 JavaScript 向不同文件夹中的 C# 控制器进行 ajax 调用