Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vscode debug embedded Python #1821

Closed
joetristano opened this issue Jan 31, 2025 · 31 comments
Closed

Vscode debug embedded Python #1821

joetristano opened this issue Jan 31, 2025 · 31 comments
Assignees

Comments

@joetristano
Copy link

Hi
I've read about this issue in multiple places, and it seems that all of the threads on it are pretty old. I would like some general guidance on how to go about the bugging and embedded python install in a C++ program.

I am able to use web_dbg without any issues. However, I would much rather use VS code.

I have tried to debug the program using 2 methods:

  1. I set up debugpy on local host and do not spin up a separate executable. With this method, I am able to see print statements in my console from the program, but I cannot stop at breakpoints
  2. Attach using process ID. This method injects the DLLs into my executable, but never finishes attaching.

I am at a complete loss I would really want to use VS code, but it seems I am out of luck and have to drop back to web debug. I'm not quite sure where to find all the different log files so any guidance would be helpful.

Thanks
Joe

@github-actions github-actions bot added the needs repro Issue has not been reproduced yet label Jan 31, 2025
@rchiodo
Copy link
Contributor

rchiodo commented Jan 31, 2025

Option 1 is likely the only way to get this to work. Remote debugging essentially. The key part for breakpoints is the path mapping.

See this wiki page for a similar example:
https://github.com/microsoft/debugpy/wiki/Debugging-over-SSH

@jtristano
Copy link

Thanks for the tips! I tried all sorts of path mappings here and nothing worked. I've obfuscated my paths to MyPath

Log files attached:
debugpy.pydevd.78812.log
debugpy.server-78812.log
debugpy.adapter-45712.log

Here's my launch


{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python Debugger: Attach using Process Id",
            "type": "debugpy",
            "request": "attach",
            "processId": "${command:pickProcess}",
            "subProcess": true,
            "consoleName": "Python Debug Console",
            "justMyCode": false,
            "pathMappings": [
                {
                    "localRoot": "c:\\**",
                    "remoteRoot": "c:\\**"
                }
            ],
            "redirectOutput": true,
            "internalConsoleOptions": "openOnSessionStart"

        },
        {
            "name": "Python: Remote Attach",
            "type": "debugpy",
            "request": "attach",
            "connect": {
                "host": "127.0.0.1",
                "port": 5678
            },
            "pathMappings": [
                {
                    "localRoot": "c:\\**",
                    "remoteRoot": "c:\\**"
                }
            ],
            "justMyCode": false,
            "debugAdapterPath": "${workspaceFolderBasename}\\MyPath\\python.exe",
            "subProcess": true,
            "consoleName": "NX Python Debug Console"
        }
    ]
}

Here's my test code


#nx: threaded
import debugpy
import time
from datetime import datetime
tmpdir_name = f"C:\\temp\\{datetime.now().strftime('%Y%m%d%H%M%S')}_debugpy"

try:
    debugpy.log_to(tmpdir_name)
except:
    pass

counter = 500


### I need to set the python program for embedded and out of process adapter 



since my program is not python
pyprogram = "C:\\MyPath\\python.exe"
code = "#nx: threaded; import debugpy; print(debugpy.__version__)"
debugpy.configure({ "python":pyprogram})

### tried in process and out of process adapter
debugpy.listen(("127.0.0.1",5678), in_process_debug_adapter=False)

print("Waiting for debugger attach " + str(counter))
counter += 1
debugpy.wait_for_client()
debugpy.debug_this_thread()
debugpy.breakpoint()
print('break on this line - right here' + str(counter))
counter += 1
debugpy.breakpoint()
print('break on this line - right here' + str(counter))
counter += 1


@rchiodo
Copy link
Contributor

rchiodo commented Jan 31, 2025

Those path mappings look wrong to me:

                     "pathMappings": [
                         {
                             "localRoot": "c:\\**",
                             "remoteRoot": "c:\\**"
                         }
                     ],

The embedded python is a windows machine? Or maybe I'm misunderstanding your situation entirely. I thought you were remoting to something like a rasberry pi.

Can you describe the application more? It's also weird that you'd need to stick debugpy in the app. Why not start your app with debugpy itself?

@jtristano
Copy link

I'm running Siemens NX which has an embedded python that I want to debug. This is windows. When I start the app, I need to set a bunch of environment variables for it to pick up my python code. I'm open to any suggestions!

Thanks
Joe

@rchiodo
Copy link
Contributor

rchiodo commented Jan 31, 2025

And Siemens NX is a C++ application? Does the python code pause at any point?

You should be able to just use the normal attach functionality in VS code without having to import debugpy into the app, but you need to have it sit there and wait.

@jtristano
Copy link

Here's the instructions from NX (yes, c++, tons of dlls) on how to integrate with pydevd in eclipse

Configure PyDev for NX Open debugging
Before you use PyDev to debug NX Open applications, you must setup the environment. PyDev can then be used to provide debugging support to scripts run by the NX embedded Python interpreter and automatic code completion support in the Eclipse editor for NX Open extension modules.

When configuring PvDev:

After installing PyDev, run Eclipse.

Choose Window→Preferences→PyDev→Interpreters→Python Interpreter and click New to add a new interpreter.

For interpreter name, use NXPython.

For interpreter executable, use python.exe of supported version. The executable is available in the local Python installation directory.

When prompted to add directories to the PYTHONPATH, select all of them and click OK.

In the newly created interpreter, in the Libraries tab, click New Folder. Add the <NX install directory>\nxbin\python directory to its PYTHONPATH at the bottom of the list or at least after the core Python libraries. This configures the <NX install directory>\nxbin\python directory as the default Python library source for this environment.

Search for the pydevd.py file in the pydev installation directory. The path of the directory may vary depending on the Eclipse version used and the Eclipse installation directory. Use New Folder to add this directory to PYTHONPATH. Pydevd.py is necessary to debug the Python script run by the embedded NX Python interpreter.

Run the debugger
When you run the debugger:

Set the following environment variable in a command prompt.

set UGII_BASE_DIR=<base dir for NX install>

Shutdown Eclipse if it is still running and restart it from the command prompt where the environment variables were set.

After you restart Eclipse, create a PyDev project.

When you create the project, for the Grammar Version option, select version 3.0.

After project creation, a PyDev Perspective is created. It is represented by the icon on the left in the PyDev-Eclipse dialog box. When a new project is created, it can be seen in the PyDev Perspective.

Debug NX Open files
When you debug files:

Import the existing Python Journal in the PyDev project. If an existing file is imported, that file is copied to the project directory from the source location and PyDev starts referring to the new copied file in the project directory.

When you open any file of the project files in the editor and import NX Open extension modules, then provide type hinting with docstring/comments manually at the time of first use of the variable, the editor provides full automatic code completion support.

For example:

# the type of the local theSession variable is made available by type hint
theSession = NXOpen.Session.GetSession() #: :type theSession: Session
To run the debug, choose Window→Open Perspective→Debug. If Debug is not present, choose Other and a dialog box is displayed. Select Debug in the dialog box and click OK.

Once the Debug Perspective opens, Terminate and Remove other debugging sessions that are still available in the Debug console.

You can press Ctrl+F8 to switch between Debug and PyDev Perspective.

Before you debug, open the file to be debugged in the editor and add # nx: threaded in the first line of the journal or script if it is not there already. The # nx: threaded flag may already be there in existing journals. For additional information, see [Run threaded extension modules with Python](https://docs.sw.siemens.com/en-US/product/209349590/doc/PL20200605194735749.nxopen_prog_guide/html/xid1124929).

If the flag is added for debugging purposes only and not for running threaded extension modules, it should not be used when you run a journal that is not being debugged. Remember to remove the flag after debugging is complete if the journal is not using threaded extension modules.

Caution:
If this flag is not added before debugging, NX crashes after debugging is complete.

Also add the following lines at the start of the file (preferably outside of any function or class):

import pydevd

pydevd.settrace()

When the settrace() call is reached, it automatically suspends execution and gives control back to the debugger.

Do not attach ugraf.exe with PyDev. If ugraf.exe is directly attached, PyDev expects it as a Python process and fails to attach it, therefore, you must use the Remote Server approach. The Remote Server is just a process not launched from within Eclipse. The Remote Server approach is another way of attaching a process to the Eclipse PyDev debugger.

To start the Remote Debugger Server from Pydev, click the appropriate icon in the PyDev menu. When it is started, it displays a message in the console to confirm that the server is listening for incoming connections.

Debugging Python scripts
You can run the NX embedded Python interpreter to debug a Python script. When you run the interpreter:

Choose File→Execute→Override Python Parameters and add the pydevd.py directory to UGII_PYTHONPATH variable. This is the same path that was added in the interpreter PYTHONPATH. This path is required because NX may not be aware of PyDev libraries.

It is important that you set the pydevd.py directory to UGII_PYTHONPATH variable before running the required journal from the PyDev project directory. If this is not done, the journal may fail with the following error:

ModuleNotFoundError: No module named 'pydevd'
If you need to debug frequently, you can add this path to the ugii_env_wnt.dat file.

Run the Python journal in the PyDev project directory to debug it (Python journal must be present in the PyDev project directory) and suspend the execution in pydevd.settrace().

If the debug server is already started in PyDev, debugging starts automatically.

If the debug server is not started, journal execution is paused at pydevd.settrace() call. When you start the debug server in PyDev, debugging starts.

You can now use PyDev to debug the script.

When debugging is complete, remove these lines from the script:

# nx:threaded

import pydevd

pydevd.settrace()

Copy the Python files back to the location where the user needs them. All of these changes are saved in files copied to the Eclipse Workspaces, not in the actual files.

Due to a debugging issue, if you expand an object in a variable window to view its different properties and values while debugging, NX fails to execute the journal.

@rchiodo
Copy link
Contributor

rchiodo commented Jan 31, 2025

You could do something like this:

import sys
import time

def wait_for_debugpy():
    while "pydevd" not in sys.modules:
        time.sleep(1)

wait_for_debugpy()

Then just do an attach from VS code using the PID of the Siemens NX process. (well assuming it loads python through the dll interface). If it starts another process, then you'd have to use the PID of that process.

There should be no need to inject pydevd or debugpy into the process yourself. The attach will do that for you.

@rchiodo
Copy link
Contributor

rchiodo commented Jan 31, 2025

Actually, that didn't work for me, it was too fast. Debugpy needs time to handle the initialize request. The script exited as soon as I attached.

This worked better:

import sys
import time
import os

print(os.getpid())

def wait_for_debugpy():
    while "debugpy" not in sys.modules:
        time.sleep(1)
    time.sleep(2) # Give time to debugpy to initialize

wait_for_debugpy()

print('after debugpy attach') # breakpoint here

Here's the launch.json I used:

    {
      "name": "Python Debugger: Attach to Process",
      "type": "debugpy",
      "request": "attach",
      "processId": "${command:pickProcess}",
    },

@rchiodo
Copy link
Contributor

rchiodo commented Jan 31, 2025

Another alternative (if you have it) is to use Visual Studio to debug python code. It supports mixed mode debugging. It would let you debug the python code and the Siemens NX code at the same time. Current version only supports 3.9 though (next preview version will support up to 3.13)

@jtristano
Copy link

Very, Cool, I'm getting there thanks to your help! I can now attach by calling debugpy.breakpoint().

I'm trying to make it repeatable now... Something for Monday!

Thank you!
Joe

@jtristano
Copy link

jtristano commented Feb 3, 2025

I'm now able to attach and I get print outs. I still cannot hit breakpoints.

When justmycode is false, I get this error
" "description": "[WinError 2] The system cannot find the file specified: 'C:\\CAD\\threading.py'",
I dont know where that's coming from unless it grabs the working dir from the process? ( c:\cad is an open handle in the process).

When justmycode is true, I get prints but no breakpoints...

I cannot step through the code b/c of the file not found error.. I have no idea where the system is grabbing C:\CAD from....

Thanks
Joe

            }

D+00002.156: /handling #9 request "threads" from Client[1]/
             Client[1] <-- {
                 "seq": 17,
                 "type": "response",
                 "request_seq": 9,
                 "success": true,
                 "command": "threads",
                 "body": {
                     "threads": [
                         {
                             "id": 1,
                             "name": "MainThread"
                         },
                         {
                             "id": 2,
                             "name": "Dummy-2"
                         }
                     ]
                 }
             }

D+00002.156: /handling #28 event "thread" from Server[1]/
             Client[1] <-- {
                 "seq": 18,
                 "type": "event",
                 "event": "thread",
                 "body": {
                     "reason": "started",
                     "threadId": 1
                 }
             }

D+00002.156: /handling #30 event "thread" from Server[1]/
             Client[1] <-- {
                 "seq": 19,
                 "type": "event",
                 "event": "thread",
                 "body": {
                     "reason": "started",
                     "threadId": 2
                 }
             }

D+00002.234: Client[1] <-- {
                 "seq": 20,
                 "type": "event",
                 "event": "output",
                 "body": {
                     "category": "stdout",
                     "output": "Attaching to PID: 38008 (elapsed: 2.01s).\n"
                 }
             }

D+00002.281: Client[1] --> {
                 "seq": 10,
                 "type": "request",
                 "command": "threads"
             }

D+00002.281: /handling #10 request "threads" from Client[1]/
             Server[1] <-- {
                 "seq": 13,
                 "type": "request",
                 "command": "threads"
             }

D+00002.281: Server[1] --> {
                 "pydevd_cmd_id": 502,
                 "seq": 34,
                 "type": "response",
                 "request_seq": 13,
                 "success": true,
                 "command": "threads",
                 "body": {
                     "threads": [
                         {
                             "id": 1,
                             "name": "MainThread"
                         },
                         {
                             "id": 2,
                             "name": "Dummy-2"
                         }
                     ]
                 }
             }

D+00002.281: /handling #10 request "threads" from Client[1]/
             Client[1] <-- {
                 "seq": 21,
                 "type": "response",
                 "request_seq": 10,
                 "success": true,
                 "command": "threads",
                 "body": {
                     "threads": [
                         {
                             "id": 1,
                             "name": "MainThread"
                         },
                         {
                             "id": 2,
                             "name": "Dummy-2"
                         }
                     ]
                 }
             }

D+00002.484: Server[1] --> {
                 "pydevd_cmd_id": 157,
                 "seq": 36,
                 "type": "event",
                 "event": "stopped",
                 "body": {
                     "reason": "exception",
                     "description": "[WinError 2] The system cannot find the file specified: 'C:\\\\CAD\\\\threading.py'",
                     "threadId": 2,
                     "preserveFocusHint": false,
                     "text": "FileNotFoundError",
                     "allThreadsStopped": true
                 }
             }

D+00002.484: /handling #36 event "stopped" from Server[1]/
             Client[1] <-- {
                 "seq": 22,
                 "type": "event",
                 "event": "stopped",
                 "body": {
                     "reason": "exception",
                     "description": "[WinError 2] The system cannot find the file specified: 'C:\\\\CAD\\\\threading.py'",
                     "threadId": 2,
                     "preserveFocusHint": false,
                     "text": "FileNotFoundError",
                     "allThreadsStopped": true
                 }
             }

@rchiodo
Copy link
Contributor

rchiodo commented Feb 3, 2025

It might be how threading.py is being loaded, but yes it looks like it's using the current directory. The pydevd.log is the one that should have more information. It will show why it can't bind the breakpoints.

@rchiodo
Copy link
Contributor

rchiodo commented Feb 3, 2025

The file not found error is also a red herring. It's because you have justMyCode = false. It means the debugger stops all on exceptions, not just the ones in your code.

Your root problem is the debugger not being able to bind breakpoints. The pydevd log should say what mapping it tried.

It might also be it's not waiting long enough. What does your actual code you're running look like?

@jtristano
Copy link

Does this matter?

I+00004.672: /handling #2 request "attach" from Client[1]/
             Session[1] waiting for connection from debug server...

I+00005.437: Injector[PID=23392] output: 0.11s - Debugger warning: The os.path.realpath.__code__.co_filename (ntpath.py)

I+00005.437: Injector[PID=23392] output: 0.00s - is not absolute, which may make the debugger miss breakpoints.

I+00005.437: Injector[PID=23392] output: 0.00s - Note: Debugging will proceed. Set PYDEVD_DISABLE_FILE_VALIDATION=1 to disable this validation.

I've attached my code and logs

#nx: threaded
import os
import time
from datetime import datetime
import sys
import sysconfig
tmpdir_name = f"C:\\temp\\{datetime.now().strftime('%Y%m%d%H%M%S')}_debugpy"
import ctypes   
PLUGIN_DIR = os.getenv("UGII_PYTHON_LIBRARY_DIR")
pyprogram = f"{PLUGIN_DIR}\\python.exe"

def wait_for_debugpy():

    # Add the python_zip directory to sys.path
    python_zip_path = os.path.join(PLUGIN_DIR, 'Lib', 'python_zip')
    if python_zip_path not in sys.path:
        sys.path.insert(0, python_zip_path)


    
    debugpy_found = False
    i = 0

    while "debugpy" not in sys.modules:
        time.sleep(1)
        i += 1
        if i > 30:
            ctypes.windll.user32.MessageBoxW(0, "Debugpy not found", "Error", 1)
            break
    if "debugpy" in sys.modules:
        debugpy_found = True
        
    pydev_found = False
    i = 0
    while "pydevd" not in sys.modules:
        time.sleep(1)
        i += 1
        if i > 30:
            ctypes.windll.user32.MessageBoxW(0, "Pydevd not found", "Error", 1)
            break
    if "pydevd" in sys.modules:
        pydev_found = True
        
    return debugpy_found and pydev_found

    

counter = 500

found = wait_for_debugpy()

if found:
    import time
    print("sleeping...")
    time.sleep(30)
    print("done sleeping")
    import debugpy
    try:
        debugpy.log_to(tmpdir_name)
    except Exception as e:
        print(e)


    debugpy.configure({ "python":pyprogram})

    print("Waiting for debugger attach " + str(counter))
    counter += 1

    pyprogram = "C:\\Users\\jtristano\\OneDrive - Divergent Technologies, Inc\\Documents\\GitHub\\design-app-nx-plugin\\DAPS_Plugin\\python.exe"
    code = "#nx: threaded; import debugpy; print(debugpy.__version__)"
    debugpy.breakpoint()
else:
    ctypes.windll.user32.MessageBoxW(0, "Debugpy not found 2", "Error", 1)
    
time.sleep(30)
print('break on this line - right here' + str(counter))
counter += 1
print('break on this line - right here' + str(counter))
counter += 1

debugger.vscode_b6c9183c-4c93-464f-848d-96ee3595f347.log
debugpy.adapter-58408.log

@rchiodo
Copy link
Contributor

rchiodo commented Feb 3, 2025

This does matter:

I+00005.437: Injector[PID=23392] output: 0.11s - Debugger warning: The os.path.realpath.__code__.co_filename (ntpath.py)

I+00005.437: Injector[PID=23392] output: 0.00s - is not absolute, which may make the debugger miss breakpoints.

I+00005.437: Injector[PID=23392] output: 0.00s - Note: Debugging will proceed. Set PYDEVD_DISABLE_FILE_VALIDATION=1 to disable this validation.

The original text for this error referenced this bug here:

http://bugs.python.org/issue1666807

What version of python are you using?

@joetristano
Copy link
Author

Python 3.10.9

@rchiodo
Copy link
Contributor

rchiodo commented Feb 3, 2025

You might try a newer version. That bug I referenced was fixed in 3.11 I think. 3.13 would be a better bet to make sure it works.

@joetristano
Copy link
Author

joetristano commented Feb 3, 2025

Thanks! I think im stuck at 3.10 due to the cad system prebuilt python binaries. I also use this to sidecar in an adjacent folder

https://github.com/jtmoon79/PythonEmbed4Win

Basically , I extract the python zip and update sitecustomize. Webdbg works but I'd still rather be in vscode. Can you think of anything I can do on my end with 3.10? Possibly turning frozen modules off within my environment?

@rchiodo
Copy link
Contributor

rchiodo commented Feb 4, 2025

I don't know for sure that 3.10 is the root cause of the problem. It might also depend upon how the CAD system is launching the python code.

The pydevd.log should tell us for sure if the path is the root cause of the problem. On my machine that ends up being a file called something like:

debugpy.pydevd.3428.log

@jtristano
Copy link

I"ll grab these tomorrow

@jtristano
Copy link

jtristano commented Feb 6, 2025

OK, I replaced all threading, ntpath and a few others with the non frozen (.py files) of those libs and the frozen import path errors are gone. I still cannot set breakpoints.

I cannot find the debugpy.pydevd , maybe b/c I'm logging from launch.json?

        {
            "name": "NX Attach",
            "type": "debugpy",
            "request": "attach",
            "processId": "${command:pickProcess}",
            "subProcess": true,
            "consoleName": "Python Debug Console",
            "justMyCode": false,
            "logToFile": true,

            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "${workspaceFolder}"
                }
            ]           
        }

Here's the output from the debug console

Attaching to PID: 50656 (elapsed: 1.01s).
Attaching to PID: 50656 (elapsed: 2.03s).
Attaching to PID: 50656 (elapsed: 3.04s).
Attaching to PID: 50656 (elapsed: 4.04s).
Attaching to PID: 50656 (elapsed: 5.05s).
Attaching to PID: 50656 (elapsed: 6.06s).
done sleeping
logging has already begun
Waiting for debugger attach 500
break on this line - right here501
break on this line - right here502
sleeping...
done sleeping
logging has already begun
Waiting for debugger attach 500

Here are my logs:

Thanks for all of your assistance!
Joe

clean_debugger.vscode_29161ac0-85fc-498a-89b1-5f7de9e7cc1e.log
clean_debugpy.adapter-25740.log

@rchiodo
Copy link
Contributor

rchiodo commented Feb 6, 2025

Pydevd log should be in the same spot as the other logs. logToFile is what enables it.

@jtristano
Copy link

Searched my entire c:\ -- -file doesnt exist when launching from vscode. It seems that I have to turn it off in launch.json and turn it on in the python code importing debugpy to get that file.. I will try

@rchiodo
Copy link
Contributor

rchiodo commented Feb 6, 2025

This code is supposed to setup the pydevd log. Maybe something is messing it up.

# If debugpy logging is enabled, enable it for pydevd as well
if "DEBUGPY_LOG_DIR" in os.environ:
    os.environ[str("PYDEVD_DEBUG")] = str("True")
    os.environ[str("PYDEVD_DEBUG_FILE")] = os.environ["DEBUGPY_LOG_DIR"] + str("/debugpy.pydevd.log")

PYDEVD_DEBUG_FILE is the path where it will log the pydevd log. You could also try just setting this environment variable prior to running the application.

@jtristano
Copy link

jtristano commented Feb 6, 2025

Got those logs working with DEBUGPY_LOG_DIR

debugpy.pydevd.51804.log
debugpy.server-51804.log

odd things about these logs ---

I'm embedded so debugpy.pydev tells me about roots I shouldnt see. I should not see anything AppData, There are no libs in C:\CAD\Lib either...

0.00s - LIBRARY_ROOTS ['C:\\CAD\\Lib', 'C:\\CAD\\Lib\\site-packages', 'C:\\Users\\me\\AppData\\Roaming\\Python\\Python310\\site-packages', 'C:\\Users\\me\\org\\Documents\\GitHub\\repo\\myembeddedpython\\Lib\\python_zip', 'C:\\Users\\me\\org\\Documents\\GitHub\\repo\\myembeddedpython\\Lib\\site-packages', 'Lib', 'Lib\\site-packages']

debugpy.server is also telling me wrong info now....

               sys.executable: C:\CAD\NX2212\NXBIN\ugraf.exe
                 sys.prefix: (C:\CAD)
                 sys.base_prefix: (C:\CAD)
                 sys.real_prefix: <missing>
                 site.getusersitepackages(): C:\Users\me\AppData\Roaming\Python\Python310\site-packages
                 sys.path (site-packages): C:\Users\me\org\Documents\GitHub\repo\myembeddedpython\Lib\site-packages
                 sysconfig.get_path('stdlib'): Lib(C:\CAD\Lib)
                 sysconfig.get_path('platstdlib'): Lib(C:\CAD\Lib)
                 sysconfig.get_path('purelib'): Lib\site-packages(C:\CAD\Lib\site-packages)
                 sysconfig.get_path('platlib'): Lib\site-packages(C:\CAD\Lib\site-packages)
                 sysconfig.get_path('include'): Include(C:\CAD\Include)
                 sysconfig.get_path('scripts'): Scripts(C:\CAD\Scripts)
                 sysconfig.get_path('data'): .(C:\CAD)
                 os.__file__: C:\Users\me\org\Documents\GitHub\repo\myembeddedpython\Lib\python_zip\os.pyc
                 threading.__file__: C:\Users\me\org\Documents\GitHub\repo\myembeddedpython\Lib\python_zip\threading.pyc
                 debugpy.__file__: c:\Users\me\.vscode\extensions\ms-python.debugpy-2024.14.0-win32-x64\bundled\libs\debugpy\__init__.py(C:\Users\me\.vscode\extensions\ms-python.debugpy-2024.14.0-win32-x64\bundled\libs\debugpy\__init__.py)


Whereas the other logs from the launch json way to log did not yield those libaries

Here are the logs from the unfrozen version of the code:

debugpy.pydevd.38568.log
debugpy.server-38568.log

Thanks
Joe

@rchiodo
Copy link
Contributor

rchiodo commented Feb 6, 2025

The log makes it look like the breakpoints did bind. But the trace function isn't being called. I can only hazard a guess that the Siemens NX is actually disabling tracing or is setting its own tracing. It looks like we never get called for events.

Your only recourse may be to try mixed mode debugging in Visual Studio. When Visual Studio 17.13 ships, it should support mixed mode debugging for 3.10.

@joetristano
Copy link
Author

Thanks Rich! Will keep an eye out

@joetristano joetristano closed this as not planned Won't fix, can't repro, duplicate, stale Feb 7, 2025
@jtristano
Copy link

Hi @rchiodo --- I made it a bit further with the following changes. I can now stop at a breakpoint, print a variable but the file doesnt load due to the debgugger thinking the current file is <string>

If I can get around this and find the "right" file, we are good to go!

Here's what I did.

  1. I created a powershell script to setup some env vars that I found while debugging and reading how to debug nx in eclipse:
$env:DEBUGPY_LOG_DIR = "C:\temp\"
$env:PYDEVD_LOAD_NATIVE_LIB = 0
$env:PYTHONPATH = "$daps_plugin_path\Lib\python_zip;$daps_plugin_path\DLLs;$daps_plugin_path\Lib;$daps_plugin_path;$daps_plugin_path\Lib\site-packages;C:\CAD\NX2212\NXBIN\python;$env:USERPROFILE\.vscode\extensions\ms-python.debugpy-2025.0.0-win32-x64\bundled\libs"
$env:LIBRARY_ROOTS = $env:PYTHONPATH
code .```
2. I started vscode with these envvars
3. Started NX from vscode
4. Attached, hit the breakpoint
debug py logs

D+00026.593: /handling #64 event "stopped" from Server[1]/
Client[1] <-- {
"seq": 41,
"type": "event",
"event": "stopped",
"body": {
"reason": "breakpoint",
"threadId": 1,
"preserveFocusHint": false,
"allThreadsStopped": true
}
}

D+00026.625: Client[1] --> {
"seq": 14,
"type": "request",
"command": "threads"
}

D+00026.625: /handling #14 request "threads" from Client[1]/
Server[1] <-- {
"seq": 17,
"type": "request",
"command": "threads"
}

D+00026.625: Server[1] --> {
"pydevd_cmd_id": 502,
"seq": 68,
"type": "response",
"request_seq": 17,
"success": true,
"command": "threads",
"body": {
"threads": [
{
"id": 1,
"name": "MainThread"
},
{
"id": 2,
"name": "Dummy-2"
}
]
}
}

D+00026.625: /handling #14 request "threads" from Client[1]/
Client[1] <-- {
"seq": 42,
"type": "response",
"request_seq": 14,
"success": true,
"command": "threads",
"body": {
"threads": [
{
"id": 1,
"name": "MainThread"
},
{
"id": 2,
"name": "Dummy-2"
}
]
}
}

D+00026.625: Client[1] --> {
"seq": 15,
"type": "request",
"command": "stackTrace",
"arguments": {
"threadId": 1,
"startFrame": 0,
"levels": 1
}
}

D+00026.625: /handling #15 request "stackTrace" from Client[1]/
Server[1] <-- {
"seq": 18,
"type": "request",
"command": "stackTrace",
"arguments": {
"threadId": 1,
"startFrame": 0,
"levels": 1
}
}

D+00026.625: Server[1] --> {
"pydevd_cmd_id": 203,
"seq": 70,
"type": "event",
"event": "module",
"body": {
"reason": "new",
"module": {
"id": 0,
"name": "main",
"path": "",
"package": "None"
}
}
}

D+00026.625: Server[1] --> {
"pydevd_cmd_id": 502,
"seq": 72,
"type": "response",
"request_seq": 18,
"success": true,
"command": "stackTrace",
"body": {
"stackFrames": [
{
"id": 3,
"name": "",
"line": 1,
"column": 1,
"source": {
"path": "",
"sourceReference": 1
}
}
],
"totalFrames": 1
}
}

D+00026.625: /handling #15 request "stackTrace" from Client[1]/
Client[1] <-- {
"seq": 43,
"type": "response",
"request_seq": 15,
"success": true,
"command": "stackTrace",
"body": {
"stackFrames": [
{
"id": 3,
"name": "",
"line": 1,
"column": 1,
"source": {
"path": "",
"sourceReference": 1
}
}
],
"totalFrames": 1
}
}

D+00026.625: /handling #70 event "module" from Server[1]/
Client[1] <-- {
"seq": 44,
"type": "event",
"event": "module",
"body": {
"reason": "new",
"module": {
"id": 0,
"name": "main",
"path": "",
"package": "None"
}
}
}

D+00026.656: Client[1] --> {
"seq": 16,
"type": "request",
"command": "source",
"arguments": {
"sourceReference": 1,
"source": {
"path": "",
"sourceReference": 1
}
}
}

D+00026.656: /handling #16 request "source" from Client[1]/
Server[1] <-- {
"seq": 19,
"type": "request",
"command": "source",
"arguments": {
"sourceReference": 1,
"source": {
"path": "",
"sourceReference": 1
}
}
}

D+00026.656: Server[1] --> {
"pydevd_cmd_id": 502,
"seq": 74,
"type": "response",
"request_seq": 19,
"success": false,
"command": "source",
"message": "Unable to retrieve source for ",
"body": {
"content": ""
}
}

E+00026.687: /handling #16 request "source" from Client[1]/
Handler 'Client.request' (file 'c:\Users\jtristano\.vscode\extensions\ms-python.debugpy-2025.0.0-win32-x64\bundled\libs\debugpy\adapter\components.py', line 143)
couldn't handle #16 request "source" from Client[1]:
Unable to retrieve source for

D+00026.687: /handling #16 request "source" from Client[1]/
Client[1] <-- {
"seq": 45,
"type": "response",
"request_seq": 16,
"success": false,
"command": "source",
"message": "Unable to retrieve source for "
}


pydevd logs


0.00s - Set tracing of frame: -
....

0.00s - Set tracing of frame: -
0.00s - SKIP set tracing of frame: c:\Users\me.vscode\extensions\ms-python.debugpy-2025.0.0-win32-x64\bundled\libs\debugpy_vendored\pydevd\pydevd.py - settrace
0.00s - SKIP set tracing of frame: c:\Users\me.vscode\extensions\ms-python.debugpy-2025.0.0-win32-x64\bundled\libs\debugpy\server\api.py - _settrace
0.00s - SKIP set tracing of frame: c:\Users\me.vscode\extensions\ms-python.debugpy-2025.0.0-win32-x64\bundled\libs\debugpy\server\api.py - connect
0.00s - SKIP set tracing of frame: c:\Users\me.vscode\extensions\ms-python.debugpy-2025.0.0-win32-x64\bundled\libs\debugpy\server\api.py - debug
0.00s - SKIP set tracing of frame: c:\Users\me.vscode\extensions\ms-python.debugpy-2025.0.0-win32-x64\bundled\libs\debugpy\public_api.py - wrapper
0.00s - SKIP set tracing of frame: c:\Users\me.vscode\extensions\ms-python.debugpy-2025.0.0-win32-x64\bundled\libs\debugpy/..\debugpy\server\attach_pid_injected.py - attach
0.00s - File traced:
0.03s - Process ThreadsRequest: {
"command": "threads",
"seq": 12,
"type": "request"
}

......

0.00s - PyDB.do_wait_suspend
name: (line: 1)
file:
event: call
arg: None
step: CMD_STEP_OVER (original step: CMD_SET_BREAK)
thread: <_MainThread(MainThread, started 1676)>, thread id: pid_55908_id_1947033666896, id(thread): 1947033666896
0.00s - Stack: , , 1
0.00s - Skipping per-thread thread suspend notification.
0.00s - Thread suspend mode: single notification
0.00s - Sending suspend notification.
0.00s - sending cmd (http_json) --> CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION {"type": "event", "event": "stopped", "body": {"reason": "breakpoint", "threadId": 1, "preserveFocusHint": false, "allThreadsStopped": true}, "seq": 64, "pydevd_cmd_id": 157}

0.00s - Process SetBreakpointsRequest: {
"arguments": {
"breakpoints": [
{
"line": 87
},
{
"line": 88
},
{
"line": 91
}
],
"lines": [
87,
88,
91
],
"source": {
"name": "trydbgpyagain_attach.py",
"path": "c:\Users\me\org\Documents\GitHub\repo\myembeddedpython_unfrozen\trydbgpyagain_attach.py"
},
"sourceModified": false
},
"command": "setBreakpoints",
"seq": 16,
"type": "request"
}

@rchiodo
Copy link
Contributor

rchiodo commented Feb 10, 2025

If the Siemen's app is running the script as a string, that would certainly make setting breakpoints ahead of time impossible. You'd have to do a manual breakpoint inside the code and then step through the 'source' that debugpy provides to VS code.

@jtristano
Copy link

jtristano commented Feb 10, 2025

Gotcha! Appreciate it... That explains why webpb works and this does not! How do I provide that code to pydevd on the vscode side?

Thanks
Joe

@jtristano
Copy link

Got it!!!!! Thank you. NX runs the first bit as a string but it cannot avoid importing my imports which get set from the run. I can use pydevd settrace!!!!!!! Thanks again for all of your help!

Joe

@judej judej removed the needs repro Issue has not been reproduced yet label Feb 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants