Skip to content

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

@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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions