tags:

views:

539

answers:

1

How do i cancel a transfer in pycurl? i use to return -1 in libcurl but pycurl doesnt seem to like that ("pycurl.error: invalid return value for write callback -1 17") return 0 doesnt work either, i get "error: (23, 'Failed writing body')" . Also how do i do a try/except with pycurl? i dont see any examples online nor the pycurl examples from the site

+1  A: 

Example code would help here. Judging from the error message, and grepping for it in the source code, you've set up a write callback. This is configured, I think, by CURLOPT_WRITEFUNCTION, and the documentation for that says:

Return the number of bytes actually taken care of. If that amount differs from the amount passed to your function, it'll signal an error to the library and it will abort the transfer and return CURLE_WRITE_ERROR.

The pycurl wrapper code checks that the value is between 0 and the number passed to it. That's why -1 failed, and why 0, triggers CURLE_WRITE_ERROR, raises the "failed writing body" exception. The pycurl code is:

 /* run callback */
 arglist = Py_BuildValue("(s#)", ptr, total_size);
 if (arglist == NULL)
     goto verbose_error;
 result = PyEval_CallObject(cb, arglist);
 Py_DECREF(arglist);
 if (result == NULL)
     goto verbose_error;

 /* handle result */
 if (result == Py_None) {
     ret = total_size;           /* None means success */
 }
 else if (PyInt_Check(result)) {
     long obj_size = PyInt_AsLong(result);
     if (obj_size < 0 || obj_size > total_size) {
         PyErr_Format(ErrorObject, "invalid return value for write callback %ld %ld", (long)obj_size, (long)total_size);
         goto verbose_error;
     }
     ret = (size_t) obj_size;    /* success */
 }
 else if (PyLong_Check(result)) {
      ... identical code for Long ...
 }
 else {
     PyErr_SetString(ErrorObject, "write callback must return int or None");
     goto verbose_error;
 }

I don't see any way in pycurl for this function to support another return value. There might be other ways, like setting up a progress callback, which does seem to allow aborts.

The relevant code in curl itself is:

/* If the previous block of data ended with CR and this block of data is
   just a NL, then the length might be zero */
if(len) {
  wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
}
else {
  wrote = len;
}

if(CURL_WRITEFUNC_PAUSE == wrote)
  return pausewrite(data, type, ptr, len);

if(wrote != len) {
  failf(data, "Failed writing body (%d != %d)", (int)wrote, (int)len);
  return CURLE_WRITE_ERROR;
}

so you can see that pycurl does not support returning the CURL_WRITEFUNC_PAUSE which curl itself allows. You can also see that curl has no way to support aborts through the write callback function. You will have to use something else.

Andrew Dalke