15

In Cython, the usual raise keyword emits C code that contains a reference to the line and name of the Cython source file, allowing a useful error message to be generated.

However, I haven't seen anything for warnings. Simply calling warnings.warn leaves the interpreter confused as to where the warning came from. I could use PyErr_WarnExplicit if there was something similar to the __LINE__ macro for pyx files.

Is there either a standard way to issue warnings or a standard way to refer to the pyx line number in Cython?

Update

This question has been open for months, so I can only assume that Cython does not presently have a good way to issue warnings. I'll leave it open here in case someone does find a way/submit a patch to make this work right.

kenm
  • 23,127
  • 2
  • 43
  • 62
  • Warnings are intended for users of your program. Why would they need line numbers? – Tobias Jun 23 '10 at 13:57
  • @Tobias - So that when they send you the output of the warning message, it's easy to see where it was emitted from. Also, the set of people who use a library often includes the set of people who do (or are willing to) maintain said library. Whether or not it's useful for the user to see the line number, the interpreter displays it along with the module it came from when it gets a warning. If you use `warnings.warn` in Cython, both the reported module and line are wrong, and this is aesthetically displeasing to me. – kenm Jun 23 '10 at 17:55
  • @geowa4 - Cython is a different beast than CPython. See: http://www.cython.org/ – kenm Jun 23 '10 at 18:00
  • woops, sorry. i had just heard so many people talking about cython meaning cpython. they were using it to differentiate between the standard impl and jython. damn naming. – geowa4 Jun 24 '10 at 13:42

1 Answers1

4

Here's something that works OK

warn.pyx:

import warnings

cdef extern from "Python.h":
    char* __FILE__

cdef extern from "Python.h":
    int __LINE__

def dowarn():
    warnings.warn_explicit("a warning", category=UserWarning, filename=__FILE__, lineno=__LINE__)

setup.py:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Compiler.Main import default_options
default_options['emit_linenums'] = True
from Cython.Distutils import build_ext


ext_modules = [ Extension("warn", ["warn.pyx"]) ]

setup(
        name = "warn",
        cmdclass = {"build_ext": build_ext},
        ext_modules = ext_modules
)

The trick is to make cython emit #line directives when generating the C code and tricking it into thinking the __FILE__ and __LINE__ are real variables that it can use. Then the warn_explicit function from warnings can be used to override the default method of determining the source file and line number.

Geoff Reedy
  • 34,891
  • 3
  • 56
  • 79