PyArg_ParseTupleAndKeywords
MRAB
python at mrabarnett.plus.com
Sat Jan 23 12:47:49 EST 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