3

I have written a small program that produces unexpected behavior.

I am using Python's C API to plot some random data using pyplot's interactive mode (plt.ion()) from my C application. But every time I call plt.draw(), apparantly rand() is reseeded with the same value. Thus, in below example code, every call to rand() produces the same value.

Is this a bug? Is it only on my machine? How can I work around this?

I am pretty sure this worked some time back. I stumbled accross this today, when I tried to compile and run some code I created and successfully tested some years ago (for the code in this answer).

I'm running Fedora 23.

This is the code:

#include <Python.h>
#include <stdlib.h>
#include <stdio.h>

int main () {
  Py_Initialize();
  PyRun_SimpleString("import matplotlib");
  PyRun_SimpleString("print matplotlib.__version__");
  PyRun_SimpleString("from matplotlib import pyplot as plt");
  //PyRun_SimpleString("plt.ion()");
  for (int i = 0; i < 10; i++) {
    // rand() returns always the same value?!
    int x = rand();
    int y = rand();
    printf("%d %d\n", x, y);
    // comment out the following line to "fix" rand() behavior:
    PyRun_SimpleString("plt.draw()");
  }
  Py_Finalize();
  return 0;
}

The output is like this:

$ gcc test.c -I/usr/include/python2.7 -lpython2.7 && ./a.out
1.4.3
1804289383 846930886
1804289383 846930886
1804289383 846930886
1804289383 846930886
1804289383 846930886
1804289383 846930886
1804289383 846930886
1804289383 846930886
1804289383 846930886
1804289383 846930886
Community
  • 1
  • 1
moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • what backend are you using? All I can imagine is that the gui framework is doing something funny to the seed / something funny is going on with forks. – tacaswell Dec 22 '15 at 23:24
  • 1
    I can not reproduce this with py3.5, gcc 5.3.0, bleeding edge mpl with the qt or tk backend. – tacaswell Dec 22 '15 at 23:35
  • 1
    nm, I _can_ reproduce this using the `agg` backend – tacaswell Dec 22 '15 at 23:37
  • I am seeing the same thing with Python2.7 and matplotlib 1.5 - I can only reproduce the bug using the Agg backend – ali_m Dec 22 '15 at 23:53
  • `plt.draw` uses `canvas.draw_idle` which lets the gui decide when to draw. Switch the draw line to `PyRun_SimpleString("plt.get_current_fig_manager().canvas.draw()");` will reproduce it with the gui backends too – tacaswell Dec 22 '15 at 23:56

1 Answers1

3

The reason for this behavior is that in the Sketch (aka XKCD) handling code there is a call to srand(0).

Michael Droettboom wrote a PR to use a local RNG for the path sketching, this should be fixed in 1.5.1+.

moooeeeep
  • 31,622
  • 22
  • 98
  • 187
tacaswell
  • 84,579
  • 22
  • 210
  • 199
  • Thanks also for the research on the affected backends! Do you think it is really necessary to reset the state of the RNG to achieve this? Or, probably it is generally unreasonable to expect third party code not to mess with the random state. – moooeeeep Dec 23 '15 at 07:38
  • @moooeeeep See update, we are fixing it in a better way. – tacaswell Dec 23 '15 at 16:23