On May 31, 2010, at 9:48 PM, Dan Stromberg wrote:
>
> I'm attempting to get a Cython module to raise exceptions that'll be
> visible to the calling CPython.
>
> The Cython code in question looks like:
> def add_from_fileno(self, fileno, length_to_add):
> exception_string = self.add_from_fileno_c(fileno, length_to_add)
> if exception_string.startswith("Buffer error"):
> raise exceptions.BufferError, exception_string
> elif exception_string == '':
> pass
> else:
> raise exceptions.AssertionError, exception_string
>
> cdef add_from_fileno_c(self, fileno, length_to_add):
> if self.would_overflow(length_to_add):
> return "Buffer error: Would overflow"
> # FIXME: We need to do something about EINTR on these 3 read's!
> if self.would_add_wrap(length_to_add):
> # do the read in two pieces
> first_length, second_length =
> self.split_to_two_add(length_to_add)
> length_added = read(fileno, &self.buffer[self.end],
> first_length)
> if length_added != first_length:
> return "length_added != first_length"
> length_added = read(fileno, self.buffer, second_length)
> if length_added != second_length:
> return "length_added != second_length"
> self.end = second_length
> else:
> # do the read in one piece
> length_added = read(fileno, &self.buffer[self.end],
> length_to_add)
> if length_added != length_to_add:
> return "length_added != length_to_add"
> self.end += length_to_add
> return ''
> ...and in the caller (CPython code, inheriting from unittest):
> def test_fileno_from_file_overflow(self):
> file_ = open('input-file', 'w')
> file_.write('abc' * 15)
> file_.close()
>
> rb = ring_buffer_mod.Ring_buffer(buffer_size = 10)
> input_fileno = os.open('input-file', os.O_RDONLY)
> for i in xrange(10):
> rb.add_from_fileno(input_fileno, 1)
> #self.assertRaises(exceptions.BufferError, rb.add_from_fileno,
> input_fileno, 1)
> try:
> rb.add_from_fileno(input_fileno, 1)
> except exceptions.BufferError:
> pass
>
> All seems fine, except for the exceptions. When I raise an
> exception in Cython, I see a message on my terminal (I believe there
> should be none), and the calling CPython code doesn't appear to
> realize that an exception has been raised. I added the
> add_from_fileno_c/add_from_file distinction, because I was hoping
> that a def would be able to raise an exception, after finding that
> cdef's and cpdef's seemed to have problems with it - but it appears
> that there's some sort of exception barrier between Cython and
> CPython.
>
> I've googled quite a bit, but haven't found much on the topic that
> didn't seem kind of hand wavey.
>
> What do I need to do, to raise an exception in Cython, that CPython
> code will be able to see?
This should work just fine for def functions, as well as c(p)def
functions not declaring a c return type (in which case you should see
[1]). Have you tried calling this directly from the command line
(eliminating the possibility that it's something with the unittest
framework?) What if you do
cdef class A:
def spam(self):
raise TypeError
cpdef eggs(self):
raise ValueError
Does that work for you? (It does for me.)
- Robert
[1]
http://docs.cython.org/src/userguide/language_basics.html#error-return-values
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev