[Python-Dev] Let's change to C API!

Antoine Pitrou solipsis at pitrou.net
Thu Aug 23 03:04:32 EDT 2018

On Thu, 23 Aug 2018 08:07:08 +0200
Jeroen Demeyer <J.Demeyer at UGent.be> wrote:
> > - the dependency / versioning problem (Cython is a large quick-evolving
> >    third-party package that we can't decently vendor)  
> Is that a real problem? You're sort of doing the same thing with pip 
> already.

Building and developing CPython doesn't depend on pip at all.  The bundled
pip copy is just an inert pack of files, as far as we are concerned.

> > - the maintenance problem (how do ensure we can change small things in
> >    the C API, especially semi-private ones, without having to submit PRs
> >    to Cython as well)  
> Why don't you want to submit PRs to Cython?

Because it forces a much longer cycle time when we want to introduce a
change in the C API: first prototype the C API change, then notice it
breaks Cython, then try to make a PR (which isn't trivial, given
Cython's size), then wait for the PR to be merged and a new Cython to
be released.

> If you're saying "I don't 
> want to wait for the next stable release of Cython", you could use 
> development versions of Cython for development versions of CPython.

But depending on the development version of a compiler isn't very
enticing, IMHO.

> > - the debugging problem (Cython's generated C code is unreadable,
> >    unlike Argument Clinic's, which can make debugging annoying)  
> Luckily, you don't need to read the C code most of the time. And it's 
> also a matter of experience: I can read Cython-generated C code just fine.

Let's be serious here.  Regardless of the experience, nobody enjoys
reading / stepping through code like the following:

  __Pyx_TraceLine(206,0,__PYX_ERR(1, 206, __pyx_L1_error))
  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_datetime); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 206, __pyx_L1_error)
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_datetime); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 206, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_utcfromtimestamp); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 206, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyFloat_DivideObjC(__pyx_v_x, __pyx_float_1e3, 1e3, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 206, __pyx_L1_error)
  __pyx_t_4 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
    if (likely(__pyx_t_4)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_DECREF_SET(__pyx_t_2, function);
  if (!__pyx_t_4) {
    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 206, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  } else {
    if (PyFunction_Check(__pyx_t_2)) {
      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 206, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    } else
    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 206, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    } else
      __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 206, __pyx_L1_error)
      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); __pyx_t_4 = NULL;
      PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_t_3);
      __pyx_t_3 = 0;
      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 206, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;



More information about the Python-Dev mailing list