PyRun_String

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Matthias

    #1

    PyRun_String

    Hello,

    I encountered a strange problem today. I try to do this:

    Log("Marker 1");
    Py_XDECREF( PyRun_String( "print 'Hi!'", Py_single_input , Dict, Dict) );
    Log("Marker 2");

    The output looks like

    Marker 1
    Hi!
    Hi!
    Marker 2

    Obviously Hi! is printed twice. I've extracted the above example of a more
    complex piece of code where you can clearly see that the statement is
    actually executed twice (not only printed). You can also see this with

    Log("Marker 1");
    Py_XDECREF( PyRun_String( "def func():\n\ti = 0\n\twhile 1:\n\t\tyield
    i\n\t\ti += 1\no=func()", Py_file_input, Dict, Dict) );
    Py_XDECREF( PyRun_String( "print o.next()", Py_file_input, Dict, Dict) );
    Log("Marker 2");


    Here the output goes

    Marker 1
    0
    1
    Marker 2


    What is the reason for this very strange behaviour? Did I do something
    wrong?

    -Matthias
  • Duncan Booth

    #2
    Re: PyRun_String

    Matthias wrote:
    [color=blue]
    > Log("Marker 1");
    > Py_XDECREF( PyRun_String( "print 'Hi!'", Py_single_input , Dict, Dict) );
    > Log("Marker 2");
    >
    > The output looks like
    >
    > Marker 1
    > Hi!
    > Hi!
    > Marker 2
    >
    > Obviously Hi! is printed twice.[/color]

    Py_XDECREF is a C macro. If you check its definition you will see that it
    does indeed evaluate the argument twice. This is a not uncommon problem
    when using macros in C: if in doubt, do not call a macro with anything
    as a parameter which has side effects.

    #define Py_XDECREF(op) if ((op) == NULL) ; else Py_DECREF(op)

    Comment

    • Matthias

      #3
      Re: PyRun_String

      Am Thu, 09 Mar 2006 20:06:54 +0100 hat Duncan Booth
      <duncan.booth@i nvalid.invalid> geschrieben:
      [color=blue]
      > Matthias wrote:
      >[color=green]
      >> Log("Marker 1");
      >> Py_XDECREF( PyRun_String( "print 'Hi!'", Py_single_input , Dict, Dict) );
      >> Log("Marker 2");
      >>
      >> The output looks like
      >>
      >> Marker 1
      >> Hi!
      >> Hi!
      >> Marker 2
      >>
      >> Obviously Hi! is printed twice.[/color]
      >
      > Py_XDECREF is a C macro. If you check its definition you will see that it
      > does indeed evaluate the argument twice. This is a not uncommon problem
      > when using macros in C: if in doubt, do not call a macro with anything
      > as a parameter which has side effects.
      >
      > #define Py_XDECREF(op) if ((op) == NULL) ; else Py_DECREF(op)[/color]

      Arrrghh, I've seen the evil side today; C macros are surely devil-sent. I
      spent hours tracking down this bug, I didn't even consider the Py_XDECREF
      and concentrated on PyRun_String. It's a pity C doesn't support inline
      functions. Thanks a lot for pointing this out before I lost my head,
      Duncan!

      Maybe Py_XDECREF(op) could be replaced with

      #define Py_XDECREF(op) {PyObject* obj = (op); if (obj == NULL) ; else
      Py_DECREF(obj)}

      but I guess this eats one or two clock cycles too much for other people
      who use Py_XDECREF.

      Thanks again!

      -Matthias

      Comment

      Working...