PyArg_ParseTupleAndKeywords
Hi, i can't understand what i'm doing wrong. I have a c/api that implements a new class. In (initproc) function i have somethink like this: [code] (some declarations omitted here) 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, "|ssii", 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; [/code] Ok, what i want is something like this: [code] import mymodule a = mymodule.myclass() # ok, this works a = mymodule.myclass(flags = 1) # bad, this won't work > TypeError: expected string or Unicode object, tuple found [/code] 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. Could you please help me? Thank you, Luca. -- http://mail.python.org/mailman/listinfo/python-list
Re: PyArg_ParseTupleAndKeywords
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, "|ssii", 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_t
Re: PyArg_ParseTupleAndKeywords
MRAB ha scritto: 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: Thank you MRAB for your reply. No, i didn't specify METH_KEYWORDS flag, but i think init method (the one that you put in tp_init slot, it is "initproc" type) doesn't have to appear in the PyMethodDef structure. Maybe i'm wrong? Luca. -- http://mail.python.org/mailman/listinfo/python-list
Re: PyArg_ParseTupleAndKeywords
MRAB ha scritto: I think you're right. I have rewritten my code, a piece at a time, and (and this is very annoying) now it works fine. I really can't understand what went wrong with my old code. Luca. -- http://mail.python.org/mailman/listinfo/python-list
get PyObject* knowing its string name
I think this sounds like a stupid question, but I searched the C/Api doc and google but I wasn't able to find any hint: how can I retrive PyObject pointer if I only know it's name? What I'd like to do is something like this: [code] PyObject* obj = PyFindWhatImLookingFor("w.z.y.x"); [/code] Of course if I know that w is a module, z is a class and so on I can search w dictionary than z members than... But I wonder if there is a way to retrive without knowing what w.z.y.x means. Thank you, Luca. -- http://mail.python.org/mailman/listinfo/python-list
C API: module cleanup function
Hi, I can't figure out if there is a way to run a specialized cleanup function when a module needs to be "unloaded" (i.e. just before a reload() or when i quit the interpreter). I'm thinking of something like tp_dealloc. If I call Py_InitModule3 and look at module->ob_type->tp_dealloc, I find that Python provides a default tp_dealloc for me. Now, suppose my module needs to allocate some resources at startup, I'm not sure, but I think I'd have to do it in my PyMODINIT_FUNC, right? But, if I reload() my module or if I quit the Python interpreter, I'd like to free those resources (before allocate them again, in case of a reload). Is there a way to make this work? Thank you, Luca. -- http://mail.python.org/mailman/listinfo/python-list
Re: C API: module cleanup function
Gabriel Genellina ha scritto: I think what you want to do isn't possible with Python 2, and it's one of the reasons the module handling was redesigned in Python 3.x; see PEP 3121. Thank you Gabriel for your help. Unlucky I can't use Python 3.x in my project, sob! Luca. -- http://mail.python.org/mailman/listinfo/python-list
Re: C API: module cleanup function
Stefan Behnel ha scritto: Gabriel already pointed you to the module cleanup support in Py3, which can be used to provide reload capabilities to your module. In Py2, there are at least some ways to free resources when terminating the interpreter. See the "atexit" module and the Py_AtExit() function: http://docs.python.org/library/atexit.html http://docs.python.org/c-api/sys.html Note that both have their specific limitations, though, as you can see from the docs. Also note that it might help you to take a look at Cython, a Python-to-C compiler for writing fast C extensions. It has an option for generating module-level cleanup code automatically, and generally simplifies writing binary extension modules quite a bit. Stefan Thank you very much Stefan for your reply, I'll study the sources you have pointed me to. Could I allocate my resources in a "static" object (without publishing the type of that object so that I can't instantiate another one) linked to my module? This way, when I stop the interpreter, the object will be destroyed calling its destructor. There's something I'm missing? Thank you, Luca. -- http://mail.python.org/mailman/listinfo/python-list
Re: C API: module cleanup function
Stefan Behnel ha scritto: Note that there is the type() builtin function which returns the type given an instance. So you can't hide the type. Argh! Yes, you are right. So I'd better have a look to Cython, right? L- -- http://mail.python.org/mailman/listinfo/python-list