PyArg_ParseTupleAndKeywords

MRAB python at mrabarnett.plus.com
Sat Jan 23 18:47:49 CET 2010


Mr.M wrote:
> Carl Banks ha scritto:
>>> (some declarations omitted here)
>>
>> You probably shouldn't have, that could be where the error is....  I'd
>> include the whole function up to the call that raises the exception.
> 
> Thank you so much Carl for your help, i'll provide more info so that you
> can try to fix my errors!
> Thank you again!
> 
> First of all i'll try to explain what i've discovered over a night i
> spent awake trying to find where the bug is.
> 
> My init behaves differently in this situations:
> 
> [code]
> # this works
> dummy = mymodule.myclass()
> 
> # this works
> dummy = mymodule.myclass("string for service")
> 
> # this also works
> dummy = mymodule.myclass("string for service", "string for event_type")
> # and it works if i provide arguments in the right sequence, of course
> 
> # this won't work
> dummy = mymodule.myclass("string for service", "string for event_type",
> free_text = "string for free_text")
> 
> # but this works
> dummy = mymodule.myclass(service = "string for service")
> 
> # the worst thing: this doesn't work but it did and i can't
> # understand what is changed
> 
> dummy = mymodule.myclass(free_text = "text for free_text")
> 
> ok, every time the code fails i get this exception:
> 
> TypeError: expected string or Unicode object, tuple found
> 
> so, i think for some reason PyArg_ParseTupleAndKeywords receives "args"
> as a touple instead of something else.
> 
> This is everything i managed to discover.
> 
> This is the code:
> 
> [code]
>         /* DEBUG INFO */
>         printf("event INIT\n");
>         if (args)
>         {
>                 int i;
>                 printf("args        = \"%s\"\n", PyString_AsString(args));
>                 printf("type        = %s\n",
> PyString_AsString(PyObject_Repr(PyObject_Type(args))));
>                 printf("tuple size  = %d\n", PyTuple_Size(args));
>                 for (i = 0; i < PyTuple_Size(args); i++)
>                 {
>                         printf("%d) %s\n", i,
> PyString_AsString(PyTuple_GetItem(args, i)));
>                 }
>         }
>         else
>         {
>                 printf("args = NULL\n");
>         }
>         printf("dict:\n");
>         if (keywords)
>         {
>                 printf("     = %s\n",
> PyString_AsString(PyObject_Repr(keywords)));
>                 printf("type = %s\n",
> PyString_AsString(PyObject_Repr(PyObject_Type(keywords))));
>         }
>         else
>         {
>                 printf("keywords = NULL\n");
>         }
> 
>     char* service          = NULL;
>     char* event_type       = NULL;
>     char* free_text        = NULL;
>     char* group_uid        = NULL;
>     char* remote_name      = NULL;
>     char* remote_abook_uid = NULL;
> 
>     time_t start_time   = -1L;
>     time_t end_time     = -1L;
>     time_t storage_time = -1L;
> 
>     int flags = 0;
> 
>     int bytes_sent     = -1;
>     int bytes_received = -1;
> 
>     PyObject* temp;
> 
>     static char* keywordlist[] = {"service",
>                                   "event_type",
>                                   "free_text",
>                                   "group_uid",
>                                   "remote_name",
>                                   "remote_abook_uid",
>                                   "start_time",
>                                   "end_time",
>                                   "storage_time",
>                                   "flags",
>                                   "bytes_sent",
>                                   "bytes_received",
>                                   NULL};
> 
>     if (!PyArg_ParseTupleAndKeywords(args, keywords, "|ssssssiiiiii",
> keywordlist,
>                                      &service,
>                                      &event_type,
>                                      &free_text,
>                                      &group_uid,
>                                      &remote_name,
>                                      &remote_abook_uid,
>                                      &start_time,
>                                      &end_time,
>                                      &storage_time,
>                                      &flags,
>                                      &bytes_sent,
>                                      &bytes_received))
>     {
>         return -1;
>     }
> 
>     printf("PyArg_ParseTupleAndKeywords worked fine\n");
> 
> [/code]
> 
> (sorry if my code is a little messy and my english rather bad!)
> 
>> Are you sure that PyArg_ParseTupleAndKeywords is what's raising the
>> error?
> 
> Yes, i think so. I have a lot of printf in my code!
> 
>> Are you subclassing this type in Python, and passing one of the string
>> parameters a tuple by mistake?  For instance, did you do something
>> like this:
>>
>> class myclass(_mycmodule._myctype):
>>     def __init__(self,*args,**kwargs):
>>         log_something_here()
>>         super(myclass,self).__init__(args,**kwargs)
>>
>> Note the missing * on args.
> 
> no, i'm not subclassing.
> I have to admit that i had some testcase and a few weeks ago they worked
> like a charm... i can't understand what i changed, of course.
> 
>>
>>
>>> I found that if i write this everything works fine:
>>>
>>> [code]
>>> import mymodule
>>> a = mymodule.myclass(service = "blabla", event_type = "event", free_text
>>>   = "free", group_uid = "group", remote_name = "remote name",
>>> remote_abook_uid = "abook", start_time = 1, end_time = 61, storage_time
>>> = 61, flags = 2)
>>> [/code]
>>>
>>> in other words, the code only works if *EVERY* argument is specified in
>>> exactly the same position it appears in keyword-null-terminated array.
>>
>> That it would have to be in a certain order is strange.  Are you sure
>> it's just not merely that they all have to be present?
>>
> 
> No, i tryied to remove the "|" and Python complains that 12 argument 
> must be present. So they are, in a sense, optional, but (and this is 
> strange), they must be present in the right order even i provide them 
> with keyword arguments.
> 
>> Tricky, but I think it'd help if you provided more information.  My
>> gut feeling is that there exception is being raised somewhere other
>> than you think it is (i.e., not by PyArg_ParseTuple), so I'd recommend
>> adding some debugging statements to track down the exact point wher
>> the error occurs.
> 
> Ok, thank you!
> The code i posted is exactly the same i run (and it fails).
> I've no problem sending you the whole module or adding any other debug 
> info you think could be helpfull to find the source of the bug.
> 
Did you specify that the method accepts keywords arguments with
METH_KEYWORDS? The function would take parameters for the instance
(self), the positional arguments (args) and the keyword arguments
(kwargs).

http://docs.python.org/c-api/structures.html

If you don't use METH_KEYWORDS then it'll think that all the arguments
are positional, which is what seems to be happening:




More information about the Python-list mailing list