使用PTVS进行IronPython远程调试

4
我已经成功地在我的C#应用程序中实现了IronPython。我将所有脚本存储在数据库中,并在需要时加载它们。现在我想使用PTVS调试我的Python代码。但每当我尝试连接到远程调试器时,Visual Studio都会说我应该使用ptvsd.enable_attach()
  1. 我认为如果我启用Python引擎的调试模式就足够了
  2. 如果我需要导入ptvsd,我该如何导入脚本(inimain,...)?我也应该将它们放在我的数据库中吗?
我无法理解这些问题并尝试了很多,但没有真正起作用。
编辑: 我找出了如何使用ptvsd,我必须“包含”ptvsd模块:
//copied from: C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\Microsoft\Python Tools for Visual Studio\2.0

string dir = Path.GetDirectoryName("C:\\Support\\Modules\\ptvsd");
ICollection<string> paths = myScriptEngine.GetSearchPaths();

if (dir != null && dir != "")
{
    paths.Add(dir);
}
else
{
    paths.Add(Environment.CurrentDirectory);
}

但是现在我在os.py中遇到了一个错误:

全局名称'statvfs_result'未定义

出错的代码行如下:

_copy_reg.pickle(statvfs_result, _pickle_statvfs_result,
    _make_statvfs_result)
编辑2:看起来我可以忽略全局名称的错误信息。 但是现在我收到了以下消息:

必须使用-X:Tracing和-X:Frames选项启动IronPython才能支持PTVS远程调试。

编辑3:我通过使用以下代码解决了跟踪和帧的错误。
        Dictionary<string, object> options = new Dictionary<string, object>();
        options["Debug"] = true;
        options["Tracing"] = true;
        options["Frames"] = true;
        myScriptEngine = Python.CreateEngine(options);

但现在我遇到了下一个问题,我无法将Visual Studio连接到我的应用程序,我总是收到以下错误消息:
“无法连接到本地主机的 Python 远程进程 'localhost:5678'。请确保该进程正在运行,并已调用 ptvsd.enable_attach() -” 编辑4: 我的Python代码:
# -----------------------------------------------
# Framework-Root-Script
# This script is the main-framework script
#  Autor: BE
#  Date: 07.10.2013
# -----------------------------------------------

# --------------------------------------------
import sys
#import atexit
import ptvsd

ptvsd.enable_attach(None)
#ptvsd.wait_for_attach()

#
from System import *
from System.Windows import MessageBox
from System.Windows.Controls import Grid, MenuItem
from ESS.MS.Base import GlobalSettings
from ESS.MS.Framework.Core.TaskbarNotification import TaskbarNotificationManager
from ESS.MS.Framework.UIG.Mask import DynamicMaskManager
# --------------------------------------------

# --------------------------------------------
#<summary>
#Eine Instanz dieser Klasse wird automatisch mit
#dem Start des DocCenter Studios erstellt.
#</summary>
class StudioInstance:

    # --------------------------------------------
    # Declarations

    # --------------------------------------------

    # --------------------------------------------
    # Constructor
    def __init__(self): 
        pass 
    # --------------------------------------------

    # --------------------------------------------
    # Will be called before the Login-Window open
    def BeforeUserLogin(self):
        try:
            pass
        except:
            pass
    # --------------------------------------------

    # --------------------------------------------
    #<summary>
    #Wird ausgeführt, wenn der Login für einen Benutzer
    # Fehlschlägt
    #</summary>
    #<param Name="InputUserName">Eingegeber Benutzername</param>
    #<param Name="InputDomain">Eingegebene Domain<param>
    def LoginFailed(self, InputUserName, InputDomain):
        try:
            pass
        except:
            pass
    # --------------------------------------------

    # --------------------------------------------
    # Will be called if the Login-Process is complete
    def LoginComplete(self, UserName, Domain):
        try:
            # -------------------------------------------------------------------
            # Control auf das Tray-Icon setzten (Linksklick)
            # Mask = DynamicMaskManager.Singleton.GetMaskInstance("Win_DCC_Bediener", False)

            # grid = Grid()
            # grid.Children.Add(Mask.VisualElement)

            # TaskbarNotificationManager.Singleton.AddTrayPopupControl(grid)
            # -------------------------------------------------------------------

            # -------------------------------------------------------------------
            # Context-Menu einttrag auf das Tray-Icon setzten
            # test = MenuItem()
            # test.Header = "Hallo Welt"
            # TaskbarNotificationManager.Singleton.AddContextMenuItem(test)
            # -------------------------------------------------------------------
            pass
        except Exception, e:
            MessageBox.Show(e.ToString())
    # --------------------------------------------

    # --------------------------------------------
    # Will be called synchron with the UI (same thread)
    def SyncUpdate(self):
        try:
            pass
        except Exception, e:
            MessageBox.Show(e.ToString())
    # --------------------------------------------

    # --------------------------------------------
    # Will be called in a custom thread
    def AsyncUpdate(self):
        try:
            pass
        except:
            pass
    # --------------------------------------------

# --------------------------------------------

编辑5 我认为现在我已经能够连接到进程了。但是当我点击Visual Studio调试器窗口中的刷新按钮时,Visual Studio挂起,并且程序不再响应。

刷新按钮: Scrennshot

也许有人可以帮助我,谢谢!


你能展示一下你用来在脚本中加载和启用ptvsd的Python代码吗? - Pavel Minaev
好的,我已经在__EDIT 5__上添加了我的代码。 - BendEg
你在上次编辑中提到的“刷新按钮”是什么? - Pavel Minaev
谢谢您的评论。我已经添加了一个带有刷新按钮的截图。 - BendEg
这看起来好像你没有连接到任何东西。如果与您的进程的连接成功,您应该在“可用进程”列表中看到它,并能够在对话框底部单击“附加”。如果您在列表中看不到它,则未检测到它。所有“刷新”所做的就是通过再次ping服务器来重新查询进程列表。 - Pavel Minaev
2个回答

1
假设该进程正在运行于localhost,并且您已经调用了ptvsd.enable_attach(),那么问题可能是防火墙相关的。您可能需要调整Windows防火墙以允许连接到该端口(我认为本地主机连接通常是被允许的,但我不确定)。

谢谢您的回复,但是关闭防火墙并没有帮助。也许问题在于我没有任何Python文件,我只是将我的脚本从数据库中复制到了Visual Studio项目(Python项目)中。 - BendEg
我建议从命令提示符中运行netstat -a -n | findstr LISTEN,并确保在运行IronPython的计算机上打开了该端口。 - Dino Viehland
如果我执行:__netstat -a -n | findstr LISTEN__,我会得到没有结果。如果我执行:__netstat -a -n__,我可以找到以下行:__TCP 0.0.0.0:5678__。 - BendEg
好的,我不知道怎么做,但现在“我可以附加到进程”,但我的Visual Studio没有给出任何“反馈”。现在__netstat -a -n__给出以下结果:__TCP 127.0.0.1:5678 127.0.0.1:63744 CONNECTED__。 - BendEg
当你说VS没有给任何反馈时,你指的是什么?所有附加应该自己做的就是将你的VS切换到调试视图,也就是你应该能看到自动和调用堆栈窗口。但由于代码仍在运行,它不会在这些窗口中显示任何内容 - 你需要在某个地方设置断点并命中它,或使用“暂停”按钮。 - Pavel Minaev
我的意思是,如果我在 VS 窗口中按下刷新按钮(请参见我的问题中的图像),Visual Studio 就会冻结,我必须通过任务管理器终止该进程。 - BendEg

0

你应该阅读attach_server.py并在其中插入一些日志输出,特别是server_thread_func()。 仔细查看并在从连接开始到附加过程中的某些点上放置调试输出。 找到它失败的地方,你就会明白原因。 现在你可以修复它。

还要在visualstudio_py_util.py :: write_bytes()等中添加调试输出,这样你就会明白发送和接收到/来自调试套接字的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接