8000 list comprehensions don't see local variables in pdb in python3 · Issue #65360 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

list comprehensions don't see local variables in pdb in python3 #65360

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

Closed
kay mannequin opened this issue Apr 5, 2014 · 14 comments
Closed

list comprehensions don't see local variables in pdb in python3 #65360

kay mannequin opened this issue Apr 5, 2014 · 14 comments
Labels
3.7 (EOL) end of life 3.8 (EOL) end of life 3.9 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error

Comments

@kay
Copy link
Mannequin
kay mannequin commented Apr 5, 2014
BPO 21161
Nosy @birkenfeld, @blueyed, @bitdancer, @florentx, @xdegaye
PRs
  • bpo-21161: pdb: default: handle list comprehensions #15194
  • Files
  • genexp.patch
  • default.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2014-04-05.19:33:03.596>
    created_at = <Date 2014-04-05.11:55:43.293>
    labels = ['interpreter-core', '3.8', 'type-bug', '3.7', '3.9']
    title = "list comprehensions don't see local variables in pdb in python3"
    updated_at = <Date 2019-12-05.21:44:31.558>
    user = 'https://bugs.python.org/kay'

    bugs.python.org fields:

    activity = <Date 2019-12-05.21:44:31.558>
    actor = 'inducer'
    assignee = 'none'
    closed = True
    closed_date = <Date 2014-04-05.19:33:03.596>
    closer = 'georg.brandl'
    components = ['Interpreter Core']
    creation = <Date 2014-04-05.11:55:43.293>
    creator = 'kay'
    dependencies = []
    files = ['34791', '35305']
    hgrepos = []
    issue_num = 21161
    keywords = ['patch']
    message_count = 10.0
    messages = ['215595', '215625', '215876', '215963', '215966', '215967', '216033', '216171', '218847', '348829']
    nosy_count = 8.0
    nosy_names = ['georg.brandl', 'blueyed', 'inducer', 'r.david.murray', 'flox', 'xdegaye', 'Jurko.Gospodneti\xc4\x87', 'kay']
    pr_nums = ['15194']
    priority = 'normal'
    resolution = 'wont fix'
    stage = None
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue21161'
    versions = ['Python 3.1', 'Python 3.2', 'Python 3.3', 'Python 3.4', 'Python 3.5', 'Python 3.6', 'Python 3.7', 'Python 3.8', 'Python 3.9']

    @kay
    Copy link
    Mannequin Author
    kay mannequin commented Apr 5, 2014

    Using generators in pdb are very handy but since Python3 they don't work properly. For example:

    import pdb
    def foo():
      items = [1, 2, 3]
      limit = 5
      pdb.set_trace()
    
    foo()

    in pdb prompt the following fails:

    (pdf) all(x < limit for x in items)
    *** NameError: global name 'items' is not defined

    I can express that in a lambda expression (i.e. pass items as an argument) but this seems unnecessary and very inelegant.

    @kay kay mannequin added interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error labels Apr 5, 2014
    @birkenfeld
    Copy link
    Member

    Your failure appears to be not pasted from an interpreter session; the actual failure is:

    (Pdb) all(x < limit for x in items)
    *** NameError: global name 'limit' is not defined

    (i.e. "limit" is not found, not "items"). This actually does not work in Python 2 either. What did work in Python 2 and doesn't work in 3, is using a list comprehension like

    all([x < limit for x in items])

    This is because list comprehensions are now implemented with their own function object like generator expressions have always been. To make the code in pdb compile "as if" it was put in the debugged function will be as good as impossible, so I'm closing this as won't fix.

    @JurkoGospodneti
    Copy link
    Mannequin
    JurkoGospodneti mannequin commented Apr 10, 2014

    Just ran into this problem and it's sooooo uncomfortable
    researching dynamic structures at run-time using PDB
    without this. :-(

    As a workaround, you can use a trick similar to this one
    to 'import' your locals into the list comprehension body:

    [l'r' for l in (locals(),) for x in l['some_local']]

    assuming 'r' & 'some_local' are two local variables in
    your surrounding scope.

    Ugly, but at least it can be made/forced to work if needed...

    Best regards,
    Jurko Gospodnetić

    @xdegaye
    Copy link
    Mannequin
    xdegaye mannequin commented Apr 12, 2014

    FWIW this generator expression can be evaluated with the 'interact' command:

    --Return--
    > /test/comprehension.py(5)foo()->None
    -> pdb.set_trace()
    (Pdb) interact
    *interactive*
    >>> all(x < limit for x in items)
    True
    >>> 
    (Pdb)

    @xdegaye
    Copy link
    Mannequin
    xdegaye mannequin commented Apr 12, 2014

    The runcode() method of InteractiveInterpreter in code.py uses the 'self.locals' dictionary as the 'globals' parameter of the invoked exec() function. And the do_interact() method of Pdb instantiates InteractiveInterpreter with 'locals' as a merge of the current frame's locals and globals dictionary. This explains why the interact command of pdb evaluates sucessfully the generator expression: the generator function object is evaluated by the interpreter in a frame where 'locals' is NULL (see fast_function() in ceval.c) and 'globals' includes now the debugged frame locals dictionary.

    So a fix for this problem is to have the default() method of pdb be implemented in the same manner as do_interact() and the runcode() method of InteractiveInterpreter. The attached patch does this.

    @JurkoGospodneti
    Copy link
    Mannequin
    JurkoGospodneti mannequin commented Apr 12, 2014

    Thanks for looking into this Xavier.

    Could someone reopen this issue so it can gets looked at again?

    @xdegaye
    Copy link
    Mannequin
    xdegaye mannequin commented Apr 13, 2014

    The NameError exception occuring on a generator expression referencing a local variable when the generator is called within exec() is the object of multiple entries in the bug tracker, see bpo-13557.

    msg 149096 in this issue suggests using exec(code, locals()) to fix the problem. It seems that what does currently the do_interact() method, and what is proposed in the patch is the recommended practice to handle this problem.

    @xdegaye
    Copy link
    Mannequin
    xdegaye mannequin commented Apr 14, 2014

    Interestingly, the interact command was added at changeset:

    $ hg log -v --pager cat -r $(hg blame Lib/pdb.py | grep do_interact | awk -F : '{print $1}')
    changeset:   66691:c2578a68879d
    user:        Georg Brandl <georg@python.org>
    date:        Sat Dec 04 11:20:26 2010 +0000
    files:       Doc/library/pdb.rst Lib/pdb.py Misc/NEWS
    description:
    Add the "interact" pdb command from pdb++.

    And the included documentation, added at that time, states (emphasis added by me):
    Start an interative interpreter (using the code module) whose global namespace contains all the ***(global and local)*** names found in the current scope.

    I can provide a test case for the patch when this issue is re-opened, unless someone else is willing to do it.

    @xdegaye
    Copy link
    Mannequin
    xdegaye mannequin commented May 20, 2014

    The patch fails to invoke exec() with the locals argument set to the current frame locals.
    The attached patch fixes this, and test_pdb runs now fine with it.

    @blueyed
    Copy link
    Mannequin
    blueyed mannequin commented Aug 1, 2019

    Georg, please consider re-opening.
    This patch here appears to fix this after all.

    @blueyed blueyed mannequin added 3.7 (EOL) end of life 3.8 (EOL) end of life 3.9 only security fixes labels Aug 1, 2019
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @hstojic
    Copy link
    hstojic commented Jan 11, 2023

    will this be fixed at any point? its really a nuisance when debugging

    @gvanrossum
    Copy link
    Member

    This came up in https://discuss.python.org/t/inlining-comprehensions-what-are-the-compatibility-constraints/22527/25

    Reopening.

    @carljm
    Copy link
    Member
    carljm commented Mar 9, 2023

    #101441 (PEP 709) will fix this for list, dict, and set comprehensions, but not for generator expressions.

    @gaogaotiantian
    Copy link
    Member

    Fixed by #111094

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.7 (EOL) end of life 3.8 (EOL) end of life 3.9 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    5 participants
    0