Skip to content

Make it possible to provide scope to/store scope of Python function #1742

Closed
@ingomueller-net

Description

@ingomueller-net

Issue description

A lambda function constructed with a certain scope (local and global) from within py::eval cannot be called, as the scope is unavailable when the function is called.

Reproducible example code

#include <pybind11/embed.h>

namespace py = pybind11;

int main(int, char**) {
    py::scoped_interpreter guard{};
    auto global = py::dict(py::module::import("__main__").attr("__dict__"));
    auto local = py::dict();
    local["x"] = 42;
    py::function f = py::eval("lambda: x", global, local);
    py::print("defined f");
    f();
    py::print("called f");
}

Output:

defined f
terminate called after throwing an instance of 'pybind11::error_already_set'
  what():  NameError: name 'x' is not defined

Initial discussion

The problem is that the local variable a is not available when f is called; in fact, f does not seem to have a scope.

Note that the following works in Python:

def make_f():
    a=42
    return eval('lambda: a')
a=123
print(make_f()())   # outputs 123

I have no idea how, but it would be great if there was a way to provide a scope to py::functions to make above example work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions