FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Exception when passing a custom python object as the parameter · Issue #412 · pythonnet/pythonnet · GitHub

Repository navigation

Exception when passing a custom python object as the parameter #412

Open

Description

Environment

  • Pythonnet version: v2.2.2
  • Python version: 3.5 64bit
  • Operating System: Windows 10

Details

I want to call a .NET method from python and pass a python object as the parameter. If the .NET function declare the argument type as PyObject, everything is fine, however, if declare the argument type as object or dynamic, exception raised.

In my project, the exception is “System.OverflowException” in GetManagedObject method in managedtype.cs.
In order to reproduce it, I built a minimal example, but a new exception raised "TypeError : No method matches given arguments".

These two exception may have some relationship, so I put this one here first since it has a way to be reproduced.

public object callback(dynamic _para)    //TypeError : No method matches given arguments
public object callback(object _para)     //TypeError : No method matches given arguments
public object callback(PyObject _para)   //passed

This is similar to this issue and this PR fixed it. I tested it, when passing an int or string object the function of 2nd and 3rd signature can be found, but when passing a python object, exception raised.

Here is the minimal example,

using System;
using Python.Runtime;

namespace pythonnetTest
{
    public class CallbackBug
    {
        public void Main()
        {
            PythonEngine.Initialize();
            using (Py.GIL())
            {
                dynamic sys = PythonEngine.ImportModule("sys");
                sys.attr1 = new Callback();
                PythonEngine.Exec(
                    "import sys\n" +
                    "class template(object):\n" +
                    "    def __init__(self):\n" +
                    "        self.value = None\n" +
                    "    def write(self, msg):\n" +
                    "        self.value = msg\n" +
                    "para = template()\n" +
                    //call .NET method and pass a custom python object as the parameter
                    "sys.attr2 = sys.attr1.callback(para)\n" + 
                    "sys.attr3 = para.value\n"
                );
                Console.WriteLine(sys.attr2.value);
                Console.WriteLine(sys.attr3);
            }
        }
    }
    public class CallbackValue
    {
        public int value;
    }
    public class Callback
    {
        public object callback(dynamic _para)  //TypeError : No method matches given arguments
        //public object callback(object _para) //TypeError : No method matches given arguments
        //public object callback(PyObject _para)   //passed
        {
            using (Py.GIL()) //attension
            {
                dynamic para = _para;
                para.write("123");
            }
            return new CallbackValue() { value = 100};
        }
    }
}

Activity

  1. vmuriart commented on Mar 2, 2017

    Contributor

    I wonder if this ever worked. Can you try to reproduce this using v2.0.0(python 2 only) or v.2.1.0.dev0 before #151 (works upto PY34). If you can't thats ok, but it would greatly narrow down where to look to fix this.

  2. yagweb commented on Mar 3, 2017

    ContributorAuthor

    @vmuriart I tested it with v2.0.0 (python2.7) and it failed with the same exception. v2.0.0 performs even worse than the current version, details was given as comments in the test code.

    Since there are many API not available in v2.0.0, so I wrote a new test, it's more concise and shown as below.

    The origin PythonEngine.RunString method in v2.0.0 has a bug, I fixed it in order to run the test.

    namespace pythonnetTest
    {
        public class CallbackBug
        {
            public static void TestHighOrderFunction2()
            {
                PythonEngine.Initialize();
                var gil = PythonEngine.AcquireLock();
                PythonEngine.RunString(
                    "import sys\n" +
                    "class MyInt(object):\n" +
                    "    def __init__(self, value):\n" +
                    "        self.value = value\n" +
                    "from pythonnetTest import CallbackBug\n" +
                    "CallbackBug.callback(1)\n" +                //v2.0.0 failed here!
                    "CallbackBug.callback_o(1)\n" +
                    "CallbackBug.callback_d(1)\n" +
                    "CallbackBug.callback(MyInt(2))\n" +          
                    "CallbackBug.callback_o(MyInt(2))\n" +       //current master branch failed here!
                    "CallbackBug.callback_d(MyInt(2))\n"
                );
                PythonEngine.ReleaseLock(gil);
            }
    
            public static void callback(PyObject value)
            {
                Console.WriteLine("PyObject passed");
            }
            public static void callback_o(object value)
            {
                Console.WriteLine("object passed");
            }
            public static void callback_d(dynamic value)
            {
                Console.WriteLine("dynamic passed");
            }
        }
    }
    
  3. yagweb commented on Mar 3, 2017

    ContributorAuthor

    @vmuriart By the way, how do you set up the environment to run a code snippet with old version of pythonnet and other version of Python?

  4. vmuriart commented on Mar 3, 2017

    Contributor

    Thanks for testing on v2.0.0. Sadly it didn't show what I hoped though. I'll need to dig a bit more into the code to figure out whats causing it.

    irt running on older pythonnet. Usually I write my tests on a *.py and try to run them on py2.7 against the compiled wheels we uploaded to pypi. If i need to dig into specific commits it gets trickier. Normally I check out the commit, upgrade UnmanagedExports if it wasn't on the latest version, and rebuild/install the package against the version I want to test.

    Alternatively, you can also add your tests to the test_suite and push to your fork. If you have an account on Travis and/or AppVeyor it should run the tests for you. This only works for tests running from *.py files since the embedded tests weren't working until recently.

  5. vmuriart commented on Mar 3, 2017

    Contributor

    You can setup git bisect run though I have minimal experience w it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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


      Back | FazBrowse Home | New Git URL