1

I used (Python 2.7) to iterate over a dict this way:

boost::python::list myList = myDict.items();
for(int i = 0; i < len(myList); i++)
{
     pytuple pair = extract<pytuple>(itemsView[t]);
     string memberKey = extract<string>(pair[0]);
     object member = pair[1];
}

But after upgrading to 3.7 items() no longer returns a list but a view, which materializes only after iterating over it.

If I try to initialize a list from items() it fails saying TypeError: Expecting an object of type list; got an object of type dict_items instead

How can I iterate over a Python 3+ dict using Boost Python?

Or, How could I convert the dictionary into a list?

Sturm
  • 3,968
  • 10
  • 48
  • 78
  • 2
    can't you use casting as list(dict.items())? – errno98 Jul 19 '19 at 14:55
  • That worked. What has happened is that this error was originating from another place where I try to do a similar thing but in a `proxy_dict` this time. Any ideas how to solve this next issue? The way I am doing it now is: `call_method(proxyDict.ptr(), "items");` – Sturm Jul 19 '19 at 15:06
  • Assuming on the answer you gave, you managed to solve it by now. Anyway, happy to help :) – errno98 Jul 19 '19 at 15:16
  • I've posted the lazy way of doing it (avoiding converting to a list, and iterating using stl style iterators) at https://stackoverflow.com/a/67038962/4657412 – DavidW Apr 10 '21 at 20:36

3 Answers3

1

Extending Ernest's comment the answer is casting the view to a list:

auto myList = list(myDict.items());

If is a proxy dictionary instead you need to do the following:

auto myList = list(call_method<object>(myProxyDict.ptr(), "items"));
Sturm
  • 3,968
  • 10
  • 48
  • 78
0

You can follow also this approach

boost::python::list keys = boost::python::list(global.keys());
for (int i = 0; i < len(keys); ++i) {
    boost::python::extract<std::string> extractor(keys[i]);
    if (extractor.check()) {
        std::string key = extractor();

        // access the dict via global[key] to the value
    }
}
camp0
  • 372
  • 1
  • 5
0

Another way:


object theIterable = theObjectDict.keys();
object theIterator = theIterable.attr("__iter__")();

do
{
        try
        {
            object theKey = theIterator.attr("__next__")();
            std::string memberkey = extract< std::string >( theKey );

        }
        catch(...)
        {
          PyObject*theError = PyErr_Occurred();
          if( theError )
          {
              PyObject *ptype, *pvalue, *ptraceback;
              PyErr_Fetch(&ptype, &pvalue, &ptraceback);
              if( ptype == PyExc_StopIteration )
              {
                    PyErr_Clear();
                    break;
              }
          }
          throw;
        }
} while(1);

mariosoft
  • 29
  • 2