我正在开发一个带有嵌入式IronPython脚本的C#应用程序,并且发现调用ScriptEngine对象的SetTrace方法将导致调试器在从Visual Studio 2015调试应用程序时不会在脚本文件中遇到断点(使用Python工具对于Visual Studio安装)。
实际上非常酷的是,你可以在Visual Studio中完成点击断点而工作量很少。下面的代码就是你所需要的(在这种情况下,通过Task.Run执行,所以我相信这意味着它在线程池线程上)
var options = new Dictionary<string, object>();
options["Debug"] = true;
// Create the engine with the debug option
var engine = Python.CreateEngine(options);
// Read in script from file
var source = engine.CreateScriptSourceFromFile(filename);
// Adding in out own objects from out ScriptObjects dictionary
var scope = engine.CreateScope();
foreach (var scriptObject in ScriptObjects)
{
scope.SetVariable(scriptObject.Key, scriptObject.Value);
}
// OnTraceback will check a cancellation token and throw upon cancellation
engine.SetTrace(OnTraceback);
// Execute the script
source.Execute(scope);
实际上,我说得太快了......上面的代码可以正常工作,但前提是你在第二行到最后一行取消了对SetTrace的调用。
这对我很重要...因为我们调用脚本对象的方法(我们添加到ScriptScope中的方法)不是我们想要中断的方法,所以我们不能通过简单地调用上面的代码来取消脚本执行工作线程和取消工作线程。如果我们允许这种情况发生,很可能我们可能泄漏资源(这些方法涉及第三方代码),或者行为是不可预测的(当你告诉电机移动然后杀死执行运动的线程时会发生什么)。我们使用OnTraceback来检查取消令牌,并在请求取消时抛出KeyboardInterrupt异常......至少我们知道取消不会在呼叫中发生。
此时我认为必须使用此回溯机制来实现调试器本身...所以当我们调用SetTrace时,我们基本上断开了调试器的连接。在python脚本中使用sys.gettrace会发现情况并非如此(gettrace返回None!)。此外,如果我在python脚本中完全定义跟踪处理程序,我可以点击我的断点!
似乎你必须在脚本末尾调用sys.settrace(None),否则你将在后续执行时停止命中断点(即使你在调用sys.settrace之前调用sys.settrace(None)) yourPythonHandler)...它就像在Execute调用中被释放一样。)
这将是一个很好的解决方法,除了我必须支持遗留脚本而不做任何改动......以及运行&#34; startup.py&#34;设置处理程序,然后运行主用户脚本,然后运行将跟踪设置为无的关闭脚本的脚本不起作用(上面的怪癖...设置和拆除跟踪必须在同一个调用中完成执行)。
所以......真正的问题实际上是两个问题:
1)。有没有人知道是否有办法从C#端设置跟踪处理程序,但不会破坏命中断点的能力
2)。有没有人知道可以用来取消脚本执行的不同机制,以确保我们不会调用客户端通过ScriptScope提供的脚本对象提供的方法。
我有IronPython源代码,到目前为止似乎无法理解它,看看我是如何使用SetTrace在调试器上踩踏。
如果我在Jack-in-the-Box工作的时候找到一个更简单的挫折感,泪水和深深的渴望,我会继续挖掘和回复。