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

Display order of properties of a tensor object in debugging #1525

Open
Jesbong opened this issue Feb 27, 2024 · 19 comments
Open

Display order of properties of a tensor object in debugging #1525

Jesbong opened this issue Feb 27, 2024 · 19 comments

Comments

@Jesbong
Copy link

Jesbong commented Feb 27, 2024

Can I adjust the display order of properties of a tensor object when debugging Python in vscode? Because in deep learning, we focus more on the shape of a tensor rather than specific values. Now we want to see the value of a tensor by pulling it down a long distance. This has reduced my debugging efficiency.

@karthiknadig karthiknadig transferred this issue from microsoft/vscode-python Feb 27, 2024
@int19h
Copy link
Contributor

int19h commented Feb 27, 2024

We don't officially support this, but I believe you could author a pydevd extension to customize the representation for your type - have a look at https://github.com/microsoft/debugpy/tree/main/src/debugpy/_vendored/pydevd/pydevd_plugins/extensions. Note however that we will be moving away from pydevd in the future.

However, given that ML/AI is a particularly important scenario these days, I'd love to hear more about the nature of customizations in question, so that we can properly address this in our new debugger.

@Jesbong
Copy link
Author

Jesbong commented Feb 27, 2024

The shape(dimension) of a tensor in vscode is far away from the top. Frequent need to expand and view results in low efficiency.

v2-d26e166332f23874578a00156232284e_r

And pycharm can see the type and shape without opening the variable, as shown in the figure. We are very concerned about the dimensions of tensors in ML/AI, it's so convenient.

pycharm

@Jesbong
Copy link
Author

Jesbong commented Feb 27, 2024

I believe the following issue are all about the same thing. The shape of numpy and tensor is so important for debuger in ML/AI.

#1191
pytorch/pytorch#35071
pytorch/pytorch#63855
microsoft/vscode-python#14244

@54nzg
Copy link

54nzg commented Apr 8, 2024

The shape of a variable cannot be easily viewed.Whether mouse hover will be supported in the future to see the shape of the variable.

@makaspacex
Copy link

It is obvious that everyone is very satisfied with the debugging of pycharm. If there are no patents or other restrictions, you can copy the display stype and information of pycharm. If there are restrictions, ignore my comments pls.

@makaspacex
Copy link

In addition to tensor and numpy, pycharm also has good type display support for list, tuple, dict, etc.

@haduoken
Copy link

haduoken commented May 9, 2024

I tempory use this
https://stackoverflow.com/questions/70704619/is-it-possible-to-show-variable-shapes-and-lengths-in-vscode-python-debugger-jus

image

but I strongly suggest vscode to support it natively

@ChaXxl
Copy link

ChaXxl commented Jul 4, 2024

I strongly suggest VS Code can show the len/shape of an countable object when debug, which PyCharm can do this, thanks to your work~~

@xuanhua
Copy link

xuanhua commented Aug 27, 2024

any progress on this issue ? vscode is so unefficient for debugging deep learning program

@qige96
Copy link

qige96 commented Aug 29, 2024

any progress on this issue ? vscode is so unefficient for debugging deep learning program

I made a quick attempt to follow the advice

We don't officially support this, but I believe you could author a pydevd extension to customize the representation for your type - have a look at https://github.com/microsoft/debugpy/tree/main/src/debugpy/_vendored/pydevd/pydevd_plugins/extensions. Note however that we will be moving away from pydevd in the future.

Here is how I did: find the local directory where my pydevd extensions sit, in my case is
C:\Users\ruiqi\.vscode\extensions\ms-python.debugpy-2024.10.0-win32-x64\bundled\libs\debugpy\_vendored\pydevd\pydevd_plugins\extensions\;
in the types sub-directory, create a new file called pydevd_plugin_pytorch_tensor_str.py

'''
A simple example to show tensor shape on debugger
'''
from _pydevd_bundle.pydevd_extension_api import StrPresentationProvider
from .pydevd_helpers import find_mod_attr


class PyTorchTensorShapeStr:
    def can_provide(self, type_object, type_name):
        torch_tensor = find_mod_attr('torch', 'Tensor')
        return torch_tensor is not None and issubclass(type_object, torch_tensor)

    def get_str(self, val):
        return f'shape: {val.shape}, value: {val}'

import sys

if not sys.platform.startswith("java"):
    StrPresentationProvider.register(PyTorchTensorShapeStr)

Then, reload my vscode, and I can see the shapes

image


And if you would like to see the length/shape at any possible cases, you may leverage the collections.abc.Sized type to generalise the code, like:

from _pydevd_bundle.pydevd_extension_api import StrPresentationProvider
from .pydevd_helpers import find_mod_attr


class SizedShapeStr:
    '''Displays the size of a Sized object before displaying its value.
    '''
    def can_provide(self, type_object, type_name):
        sized_obj = find_mod_attr('collections.abc', 'Sized')
        return sized_obj is not None and issubclass(type_object, sized_obj)

    def get_str(self, val):
        if hasattr(val, 'shape'):
            return f'shape: {val.shape}, value: {val}'
        return f'len: {len(val)}, value: {val}'

import sys

if not sys.platform.startswith("java"):
    StrPresentationProvider.register(SizedShapeStr)

image


Hi @ChaXxl @xuanhua @54nzg @Jesbong, I made a pull request #1661 ,which is waiting to be reviewed. In case it is not approved, perhaps you make it by yourself.

Hope this may help you.

@xuanhua
Copy link

xuanhua commented Sep 12, 2024

@qige96 glad to hear this, I will try 👍

@judej judej assigned debonte and unassigned debonte Oct 14, 2024
@xuanhua
Copy link

xuanhua commented Oct 17, 2024

@qige96 Hi,sorry for this late feedback, I just tried to add a extension under debugpy like you did.
But I got following error during lauching debugging for a python file:

Unable to load extension: pydevd_plugins.extensions.pydevd_plugin_pytorch_tensor_str

I also add the root directory to the PYTHONPATH, which is required by link: https://github.com/microsoft/debugpy/tree/main/src/debugpy/_vendored/pydevd/pydevd_plugins/extensions

But still the same error. And it cannot work both on my macbook pro and a container environment. My vscode version is debugpy-2024.12.0-darwin-arm64

Any suggestions ?

@qige96
Copy link

qige96 commented Oct 17, 2024

Unable to load extension: pydevd_plugins.extensions.pydevd_plugin_pytorch_tensor_str
I also add the root directory to the PYTHONPATH, which is required by link: https://github.com/microsoft/debugpy/tree/main/src/debugpy/_vendored/pydevd/pydevd_plugins/extensions

But still the same error. And it cannot work both on my macbook pro and a container environment. My vscode version is debugpy-2024.12.0-darwin-arm64

Hi @xuanhua , I am not sure exactly about what was going wrong with your case, but I guess you put the plugin file in the wrong directory (due to my misleading words, sorry). You should put in debugpy\_vendored\pydevd\pydevd_plugins\extensions\types directory like this

Image

If you put it in debugpy\_vendored\pydevd\pydevd_plugins\extensions, which is the parent directory, then you would get the error message as you mentioned.

Hope this help you.

@xuanhua
Copy link

xuanhua commented Oct 18, 2024

@qige96 yes, following your suggestions, I move the my added file into types directory and it works now 👍

@xuanhua
Copy link

xuanhua commented Oct 22, 2024

@qige96 , Thanks for your solution, it maks my life really better, but one more question about these pydevd extentions, I am often used to use docker container as the dev environment. And I found in a new container, I have to copied them to that container from host manually. Is there any better way to avoid such manual copying everytime lauching a totally new container

@qige96
Copy link

qige96 commented Oct 22, 2024

Is there any better way to avoid such manual copying everytime lauching a totally new container

Hi @xuanhua , if they pydevd extension can merge my code into its codebase, then all problems will be gone. However, the author of Pydevd had a concern of the code in my PR to be an over-design (which indeed I admit). I am still thinking a better design to make us AI/ML people happy, but also comfort other users. But it takes time, not only for redesigning the code, but also for all other Open Source project processes, such as code review, and the author of Pydevd still has other things to do.

For now and for you, the best way could be writing a script to do all the copying/downloading jobs, and execute that script in your Dockerfile, so that everytime you launch a new container.

@fabioz
Copy link
Collaborator

fabioz commented Oct 22, 2024

Hey, just to note, the whole plugins idea means you shouldn't need to change the debugger code for this, you can just add it to your own code or create your own library just with that (then you don't need to worry as much about all the other use cases out there -- sure, it'd be nice to have a fix in pydevd which would fix it for all, but in that case the bar is really higher so that it doesn't break unrelated use cases).

The readme https://github.com/fabioz/PyDev.Debugger/blob/main/pydevd_plugins/extensions/README.md should explain the structure you can have without adding code to pydevd.

@qige96
Copy link

qige96 commented Oct 22, 2024

Hey, just to note, the whole plugins idea means you shouldn't need to change the debugger code for this, you can just add it to your own code or create your own library just with that

Hi @fabioz , thanks for the reminder and that would be a good news for us. We don't need to bother the source repository. But I just had a quick try yet it didn't work. Here is my pydevd_plugins folder. I am sure the parent directory of pydevd_plugins was in PYTHONPATH. Could you please provide some hints on what may go erong?

pydevd_plugins
│- __init__.py
└─extensions
       - pydevd_plugin_shape_str.py
       - __init__.py
# __init__.py
try:
    __import__('pkg_resources').declare_namespace(__name__)
except ImportError:
    import pkgutil
    __path__ = pkgutil.extend_path(__path__, __name__)
# pydevd_plugin_shape_str.py
import sys
sys.path.append(r'C:\Users\ruiqi\.cursor\extensions\ms-python.debugpy-2024.6.0-win32-x64\bundled\libs\debugpy\_vendored\pydevd')
print(sys.path)

from _pydevd_bundle.pydevd_extension_api import StrPresentationProvider
# from pydevd_helpers import find_mod_attr, find_class_name

def find_mod_attr(mod_name, attr):
    mod = find_cached_module(mod_name)
    if mod is None:
        return None
    return getattr(mod, attr, None)


def find_class_name(val):
    class_name = str(val.__class__)
    if class_name.find(".") != -1:
        class_name = class_name.split(".")[-1]

    elif class_name.find("'") != -1:  # does not have '.' (could be something like <type 'int'>)
        class_name = class_name[class_name.index("'") + 1 :]

    if class_name.endswith("'>"):
        class_name = class_name[:-2]

    return class_name


class SizedShapeStr:
    '''Displays the size of a Sized object before displaying its value.
    '''
    def can_provide(self, type_object, type_name):
        sized_obj = find_mod_attr('collections.abc', 'Sized')
        return sized_obj is not None and issubclass(type_object, sized_obj)

    def get_str(self, val):
        if hasattr(val, 'shape'):
            return f'shape: {val.shape}, value: {val}'
        return f'len: {len(val)}, value: {val}'

if not sys.platform.startswith("java"):
    StrPresentationProvider.register(SizedShapeStr)

pydevd_plugins.zip

@pheotry
Copy link

pheotry commented Jan 16, 2025

Hey, just to note, the whole plugins idea means you shouldn't need to change the debugger code for this, you can just add it to your own code or create your own library just with that嘿,请注意,整个插件的想法意味着您不需要为此更改调试器代码,您可以将其添加到您自己的代码中或使用它来创建自己的库

Hi @fabioz , thanks for the reminder and that would be a good news for us. We don't need to bother the source repository. But I just had a quick try yet it didn't work. Here is my pydevd_plugins folder. I am sure the parent directory of pydevd_plugins was in PYTHONPATH. Could you please provide some hints on what may go erong?嗨,@fabioz,感谢您的提醒,这对我们来说是个好消息。我们不需要打扰源存储库。但我只是快速尝试了一下,但没有用。这是我pydevd_plugins 文件夹。我确定 pydevd_plugins 的父目录在 PYTHONPATH 中。您能否提供一些提示,说明可能会发生什么?

pydevd_plugins
│- __init__.py
└─extensions
       - pydevd_plugin_shape_str.py
       - __init__.py

init.py

try:
import('pkg_resources').declare_namespace(name)
except ImportError:
import pkgutil
path = pkgutil.extend_path(path, name)

pydevd_plugin_shape_str.py

import sys
sys.path.append(r'C:\Users\ruiqi.cursor\extensions\ms-python.debugpy-2024.6.0-win32-x64\bundled\libs\debugpy_vendored\pydevd')
print(sys.path)

from _pydevd_bundle.pydevd_extension_api import StrPresentationProvider

from pydevd_helpers import find_mod_attr, find_class_name

def find_mod_attr(mod_name, attr):
mod = find_cached_module(mod_name)
if mod is None:
return None
return getattr(mod, attr, None)

def find_class_name(val):
class_name = str(val.class)
if class_name.find(".") != -1:
class_name = class_name.split(".")[-1]

elif class_name.find("'") != -1:  # does not have '.' (could be something like <type 'int'>)
    class_name = class_name[class_name.index("'") + 1 :]

if class_name.endswith("'>"):
    class_name = class_name[:-2]

return class_name

class SizedShapeStr:
'''Displays the size of a Sized object before displaying its value.
'''
def can_provide(self, type_object, type_name):
sized_obj = find_mod_attr('collections.abc', 'Sized')
return sized_obj is not None and issubclass(type_object, sized_obj)

def get_str(self, val):
    if hasattr(val, 'shape'):
        return f'shape: {val.shape}, value: {val}'
    return f'len: {len(val)}, value: {val}'

if not sys.platform.startswith("java"):
StrPresentationProvider.register(SizedShapeStr)
pydevd_plugins.zip pydevd_plugins.zip

Your directory structure should like this:

Image

the extension directory is unnecessary in your zip file.

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