execfile() and locals()

2010-08-15 Thread fons
Hello all,

The documentation on execfile() and locals() makes it clear that code
executed from execfile() can not modify local variables in the function
from wich execfile() was called. Two questions about this:

1. Is there some way to circumvent this limitation (apart from explicitly
copying variables to/from a dictionary passed as locals to execfile()) ?

2. (for experts only I guess) I'd like to understand *why* this is the case. 

TIA,

-- 
FA

There are three of them, and Alleline.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: execfile() and locals()

2010-08-16 Thread fons
On Sun, Aug 15, 2010 at 11:24:25PM +, Steven D'Aprano wrote:

> On Sun, 15 Aug 2010 23:21:51 +0200, fons wrote:
> 
> > The documentation on execfile() and locals() makes it clear that code
> > executed from execfile() can not modify local variables in the function
> > from wich execfile() was called. Two questions about this:
> > 
> > 1. Is there some way to circumvent this limitation (apart from
> > explicitly copying variables to/from a dictionary passed as locals to
> > execfile()) ?
> 
> Chances are very good that if you're using exec or execfile inside a 
> function, you probably don't need to.

In this case that would probably be true (see below).

> As an optimization, local variables don't live inside a dict namespace. 
> The space for those locals is allocated at compile time, and locals() 
> returns a copy of the variables in a dict.
> 
> However, the action of exec is a little more subtle, and mysterious, as 
> seen by this example in Python 3.1:
> 
> >>> def f():
> ... x = 1
> ... print(locals())
> ... exec("x=2; y=0")
> ... print(locals())
> ...
> >>>
> >>> f()
> {'x': 1}
> {'y': 0, 'x': 1}
> 
> This shows that exec was able to create a new local variable, but not 
> modify an existing one -- this is completely unintuitive to me. I would 
> have guessed the opposite. And worse:
> 
> >>> f.__code__.co_varnames
> ('x',)
> >>> f.__code__.co_nlocals
> 1
> 
> So where does the newly-created local `y` live, if not in a dict 
> namespace and not in the usual variable slots?
> 
> Curiouser and curiouser... 

Indeed... and I tried your example also in 2.6, and there it 'just works'.

I've been reading a bit on execfile() and friends on various locations
on the web, and there seems to be some controversy about it. One poster
even wrote 'If you need execfile() you have a design problem'. I don't
agree - in this case I use an interpreted language exactly to be able
to do such things as made possible by execfile().

The application is a GUI one used to control electronic musical instruments
and audio processors in a 'live performance' situation. Its main window
shows a collection of buttons, rotary controls, sliders, etc., which trigger
things when used.

For example, clicking on a button could start a timed sequence of actions,
each action being e.g. a message sent to a synthesis program or an audio
processor, and/or some changes to the GUI itself.

Such a sequence could be quite complex, defining it may require loops
and conditions, or even interaction with other sequences, so the natural
way is to define it as code and not as data. Users of the system are
assumed to know basic Python, without being experts or expected to 
understand things such as the ones we are discussing.

Sequences will run for some time, many of them can run at the same time,
so each of them will be executed in a separate thread if required.

A basic requirement for the system is that all actions can be redefined
while the program is running, hence the need for execfile() or something
similar. Shift-click on a GUI item presents a menu with options to modify
its actions, one of them is to edit the file defining the code associated
with the item.

Now there are two ways to use execfile() or equivalent:

1. Actually execute the file when e.g. a button is clicked.
2. Execute it when the action is defined (i.e. when the user
has finished editing the file). In the case the file should
define a function which will be executed when triggered.

I'll probably use the second way - the function will be 
precompiled, and most errors will show up before it is
actually executed.

Ciao,

-- 
FA

There are three of them, and Alleline.

-- 
http://mail.python.org/mailman/listinfo/python-list


PyCObject_FromVoidPtr etc.

2011-03-22 Thread Fons Adriaensen
Hello all,

Upgrading to 3.2 has provided some sort of cold shower.

I have hundreds of extensions that fail to install due to
PyCObject_FromVoidPtr() and PyCObject_AsVoidPtr() not longer
being available, and I'm looking for a (hopefully) simple
solution.

In all cases, these are extensions that create an instance
of a C++ class which is purely a 'slave' to the corresponding
instance of a Python class.

They all follow a pattern illustrated by the following code:


---
#include "class_XX.h"


extern "C" void destroy (void *object)
{
Class_XX *C;

C = (Class_XX *) object;
delete P;
}


extern "C" PyObject* create (PyObject *self, PyObject *args)
{
Class_XX *C;
PyObject *P;
int a, b;

if (! PyArg_ParseTuple(args, "(Oii)", &P, &a, &b)) return NULL;
C = new Class_XX (P, a, b);
return PyCObject_FromVoidPtr((void *) C, destroy);
}


extern "C" PyObject* method_1 (PyObject *self, PyObject *args)
{
Class_XX *J;
PyObject *P;
int x, y;

if (! PyArg_ParseTuple(args, "(Oii)", &P, &x, &y)) return NULL;
C = (Class_XX *) PyCObject_AsVoidPtr(P);
P = Py_BuildValue ("(i)", C->method_1 (x, y));
Py_INCREF (P);
return P;
}

...

--


The C++ object stores a pointer to its Python equivalent (not needed
in most cases, only if there would be callbacks) and the Python object
stores a PyCObject corresponding to its C++ slave and uses this to call
its methods.

In no case there is any need of the C++ objects being visible anywhere
else, let alone in other extensions.

Is there a way to keep things (almost) as simple as this using the
'Capsules' ?? I do understand the advantage of having such a mechanism,
but in this case it's sort of overkill...

TIA,

-- 
FA






-- 
http://mail.python.org/mailman/listinfo/python-list


Callback mysteries

2011-03-24 Thread Fons Adriaensen
Hello all,

I wonder if someone could explain some of the following.

(Python 3.2)

I have a class which has a method called 'callback()'.
An instance of this class calls a C extension which
then calls back into Python.

In all cases below, two arguments are passed to the C
code and end up in 

PyObject *object;
PyObject *method;

The original solution was:

P:  self -> object,  "callback" -> method
C:  PyObject_CallMethodObjArgs(object, method, 0);

and this works nicely. 

Just out of academic interest, I was wondering if the run-time
lookup of 'callback' could be avoided. My first attempt was:

P:  self -> object, classname.callback -> method
C:  PyObject_CallFunctionObjArgs(method, object, 0); 

and this also works, I'm just not sure it's kosher.

Now in theory 'self.callback' should contain all info
that is required (or not ?). So I also tried:

P:  self -> object, self.callback -> method
C:  PyObject_CallFunctionObjArgs(method, PyMethod_Self(method), 0)

which fails,  

P:  self -> object, self.callback -> method
C:  PyObject_CallFunctionObjArgs(PyMethod_Function(method), 
PyMethod_Self(method), 0);

which also fails.

And indeed the value returned by PyMethod_Self() is not equal to 
the value of object (= self). In fact it seems not to depend on
the calling instance at all. Do I misunderstand what PyMethod_Self()
is supposed to return ?

I also tried 

P:  self -> object, self.callback -> method
C:  PyObject_CallObject(method, 0);

which also fails.

Any comments that help me understand these things will be appreciated !


Ciao,

-- 
FA




-- 
http://mail.python.org/mailman/listinfo/python-list


Re: why memoizing is faster

2011-03-24 Thread Fons Adriaensen
On Thu, Mar 24, 2011 at 08:12:22PM -0400, Terry Reedy wrote:

> The irony of this is that memoizing 'recursive' functions with a  
> decorator depends on the fact the Python does not have truly recursive  
> functions. A function cannot call itself directly.

I wonder what exactly is meant by that last sentence:

* It doesn't happen (since the function name is evaluated
  to find the function to be called, as you explained).

or

* Even if a variable pointing directly to the function
  were provided (as a global or function argument),
  calling it is not supposed to work (for some reason).

??

Ciao,

-- 
FA

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Guido rethinking removal of cmp from sort method

2011-03-28 Thread Fons Adriaensen
On Mon, Mar 28, 2011 at 11:06:20AM +0200, Antoon Pardon wrote:
 
> Asking for *real-world* uses is just how the python community smothers
> requests. 

It's quite a common strategy, I've seen it used in many
contexts. Which doesn't make it any more acceptable of
course.

> Should someone come with a use case, I expect the following
> to happenr: One will go over the case with magnifying glasses in
> search for any possible way in which it could be rewritten so as not
> to need the cmp anyway. This will probably not be a big problem because
> the person with the use case will probably have given a simplified example
> to explain the overal picture. However most people responding will
> ingnore the overal picture and focus on details that may very well work
> on the simplified example but may not in the specific real-world case.
> But since going over all details to argue the case will be too time
> consuming, in the end the person with the use case will simply fail to
> convince.

An accurate description of the process.

> Forcing people to use a key-function, will produce cases where python
> will ask for more memory and take longer to sort, than allowing to provide
> a cmp function. This for the simple reason that for some order-functions,
> the only way to write a key-function will be to write a specific class,
> that will implement the order with the same kind of code that otherwise
> would have been put in the cmp function, making the trade off: memory use
> vs speed no longer a trade off.

If cmp_to_key() would do some (probably impossible) magic - factoring
the user's cmp() into a non-trivial key mapping and a simpler and more
efficient compare - then it would make sense. But it doesn't do such
a thing. The 'key' it uses is just a copy, and the compare that will
be used finally is just the user's one. Nothing gained, just overhead
added.

> If the existance alone of such cases isn't enough to reverse the decision
> about the cmp-argument of the sort-method. My guess is that nothing will.

Sadly enough, that is probably a good guess.

Ciao,

-- 
FA

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: FBI wants public help solving encrypted notes from murder mystery

2011-03-30 Thread Fons Adriaensen
On Wed, Mar 30, 2011 at 01:25:54PM -0700, Joe Snodgrass wrote:

> For larger images of the notes go here. [LINK]

[LINK]  ???

-- 
FA


-- 
http://mail.python.org/mailman/listinfo/python-list