Problem: new type in Python 2.2

Dave Kuhlman dkuhlman at rexx.com
Wed Jan 16 17:35:28 EST 2002


Tim Peters <tim.one at home.com> wrote:
> 
> [Dave Kuhlman]
>> I've implemented a new Python type (in C). It's based on
>> Objects/xxobject.c in the source code distribution.  It implements
>> a wrapper for a compiled XSLT stylesheet and is part of the Python
>> support for libxslt.  (See http://www.rexx.com/~dkuhlman)
>>
>> It no longer works with Python 2.2.
>>
>> Here is the finger-print of the error:
>>
>>
>>     o
>>     o
>>     o
>>   File "test_to_file_compiled.py", line 28, in translate
>>       for stem in fileStems:
>> TypeError: argument 2 must be string, not libxslt_stylesheet
>>
>>
>> Where:
>>
>>     libxslt_stylesheet is the Python type that I have implemented.
>>
>>     fileStems is a list of strings.
>>
>> The error occurs when the for statement is exited, i.e. after all
>> the iterations have been completed.
>>
>> This error message does not make too much sense to me.
> 
> Cheer up, it makes no sense at all <wink>.  This is usually a symptom of a
> function in an extension module setting an error condition but neglecting to
> return NULL (or whatever the proper error return is in context).  A common

This was exactly my problem.  (How did you know that?  I had my C
source code to look at, and _I_ couldn't see that for more than two
days.) I was calling PyArg_ParseTuple twice (once to check for one
set of arguments and again to check for a second set of arguments)
without calling PyErr_Clear() when the first call to
PyArg_ParseTuple failed. Adding the call to PyErr_Clear() fixed my
problem.

> way for that to happen is for an extension to neglect to check the return of
> an API function *it* calls for errors (every call must be checked for an
> error return, and every error must be passed on or explictly cleared -- you
> can never skip these checks).  As a result, the main interpreter loop may

Oh.  I didn't know this.  Note to self:  Start paying attention to
errors and exceptions raised by Python C API functions.  I'm sure
that someone would tell me that they are there for my own good.

> miss the error at the time it occurs (the extension lied about whether an
> error did occur), and not notice until some later (and by-now irrelevant)
> opcode checks PyErr_Occurred() and picks up a stale error message.  In
> particular, the opcodes involved with for-loop setup and teardown make
> PyErr_Occurred() checks, as part of distinguishing a normal StopIteration
> loop exit from an unexpected exception.
> 
> If you build a debug-mode Python, the interpreter loop makes extra checks
> after each opcode to try to detect whether someone just lied about the error
> state.  This will point out the mistake closer to where it's really
> happening.  If mistake is found, of these msgs is printed to stderr:
> 
>                 "XXX undetected error\n"
>                 "XXX undetected error (why=%d)\n"
> 

This technique is going into my notes.  It's certainly more
effective than my brute force approach: scatter print(f) statements
everywhere.


>> ...
>> I can't find this error message in the Python 2.2 source.
> 
> Me neither -- and that's more evidence that an extension is involved.  The
> Python core is the least likely source (historical truth -- it's *almost*
> never to blame for these things, simply because the core code is so heavily
> exercised by so many people that such mistakes don't survive to see a final
> release).  It could be in your extension, or in any other extension you're
> using.

My extension module was involved and was the culprit.  And, of
course you are right: the Python core gets much more excercise than
my extension.

> 
>> ...
>> This error occurs when I run Python 2.2.  It does not occur when I
>> run Python 2.1.
> 
> Probably irrelevant once the true cause is known.  Mistakes can go
> undetected by accident.  API functions that didn't used to raise errors in
> some endcases may also start to, so sloppy use of API functions (not
> checking for error returns) can also go unpunished by accident.
> 

Perhaps Python 2.2 is a bit more careful and picky than 2.1, which
I think is a good thing.

>> ...
>> Are there some steps that I must go through ...?
> 
> Good odds of quick success:  find the function(s) in the extensions you use
> that create the message in question, and stare at their callers until you
> find the one that's improperly dealing with an error return.
> 
> 

It took approximately 3 days of staring.  With the guidance you
gave above, it would have taken a _lot_ less time.

Thanks much for help and enlightenment.

Now, if I can just find some place to save this information where
it will pop into my field of view the next time I'm about to do
this.

  - Dave



-- 
Dave Kuhlman
dkuhlman at rexx.com
http://www.rexx.com/~dkuhlman


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----



More information about the Python-list mailing list