473,509 Members | 2,763 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Injecting new names into the above frame

Dear Pythoners,

I know this will probably be perceived as 'evil voodoo', and fair
enough: it probably is. I guess it is unpythonic.

... but I want to know how to do it anyway - mostly for my own
interest.

Consider the following snippet of code:

---
def Get( *names ):
if not names: return None

frame = sys._getframe(1)
prevFrameLocals = frame.f_locals

for name in names:
prevFrameLocals[ name ] = FetchObjectNamed( name )

Get("a", "b", "c")

print a, b, c
---

FetchObjectNamed() is an arbitrary function which takes a string and
returns an object it got from some store somewhere.

This works fine at the module level, because names in the locals/
globals dictionary can be played with in this way. The idea is to save
lots of typing, i.e.

a, b, c = Get("a","b","c")

...gets frustrating after much typing for many objects with long names.
This is just an example, there are other instances I have where it
would be nice to inject names into the frame above.

Of course, we hit a road block when we call 'Get' from a function
rather than a module, because the locals dictionary does not get
copied back into the code object automatically, so we have to add this
snippet before the Get() function returns:

from ctypes import pythonapi, py_object, c_int
pythonapi.PyFrame_LocalsToFast( py_object( frame ), 1 )

This copies back the names into the code object, and works fine.. that
is, if the names already exist within the code object.

def MyFunction():
a = None
Get("a")
print a # Works
Get("b")
print b # Name error, b is undefined

Is there any way for Get() to define a new variable within
MyFunction's code object? Or is there any programmatic way to, at
runtime, insert new names into functions?

I don't care how hacky it is and whether it requires making calls to
python's internals with ctypes - maybe the whole code object needs to
be replaced? is it even possible to do that when the Get() function is
about to return to this new code object?

Cheers,

- Peter
Sep 12 '08 #1
4 1136
Peter Waller wrote:
Dear Pythoners,

I know this will probably be perceived as 'evil voodoo', and fair
enough: it probably is. I guess it is unpythonic.

.. but I want to know how to do it anyway - mostly for my own
interest.
Well, if you're really just asking out of curiosity, it should be
sufficient to tell you that this is not possible.
[...] we have to add this
snippet before the Get() function returns:

from ctypes import pythonapi, py_object, c_int
pythonapi.PyFrame_LocalsToFast( py_object( frame ), 1 )

This copies back the names into the code object, and works fine.. that
is, if the names already exist within the code object.

def MyFunction():
a = None
Get("a")
print a # Works
Get("b")
print b # Name error, b is undefined
The answer to why this doesn't work lies in the disassembly of that
function:
0 LOAD_CONST 0 (0)
3 STORE_FAST 0 (0)
6 LOAD_GLOBAL 1 (1)
9 LOAD_CONST 1 (1)
12 CALL_FUNCTION 1
15 POP_TOP
16 LOAD_FAST 0 (0) <- This is a
19 PRINT_ITEM
20 PRINT_NEWLINE
21 LOAD_GLOBAL 1 (1)
24 LOAD_CONST 2 (2)
27 CALL_FUNCTION 1
30 POP_TOP
31 LOAD_GLOBAL 2 (2) <- This is b
34 PRINT_ITEM
35 PRINT_NEWLINE
36 LOAD_CONST 0 (0)
39 RETURN_VALUE

Since you have an assignment to the name a, a is recognized as a local
name at compile time. b is not recognized as a local name at compile
time, so even if you inject a value for b into the locals dictionary,
the byte code still looks up the value as a global name.
Is there any way for Get() to define a new variable within
MyFunction's code object? Or is there any programmatic way to, at
runtime, insert new names into functions?
Not without making fundamental changes to Python itself. The fact that
this isn't possible is a feature, in my opinion. I like the fact that I
can call a function and be *absolutely certain* that it's not going to
pollute my local namespace.

Hope this helps,

--
Carsten Haese
http://informixdb.sourceforge.net
Sep 12 '08 #2
On Sep 12, 2:30*pm, Carsten Haese <carsten.ha...@gmail.comwrote:
>
The answer to why this doesn't work lies in the disassembly of that
function:
This makes me want to ask: is it difficult to modify a function's
code? Even if it weren't possible whilst the function was executing
(because then I would be returning to a function I just created, I
guess?) Could I make another function which converted this LOAD_GLOBAL
to LOAD_FAST?

I agree that in general a function should have no side effects and I
would like to know exactly what it is going to do, and that what I'm
doing is unpythonic.

My curiosity extends because I would like to get to know a bit more
about python's internals. My gut tells me there has to be a way to
achieve what I'm after - even if it the result is extremely ugly.
Maybe it might involve applying a decorator to functions who use this
functionality, who change the code so that these calls work?

Cheers for your reply,

- Pete
Sep 13 '08 #3
On Sep 13, 1:35*pm, Peter Waller <peter.wal...@gmail.comwrote:
This makes me want to ask: is it difficult to modify a function's
code?
No, it is not difficult. Look at the byteplay module:
it makes possible all kinds of dirty hacks.
Sep 13 '08 #4
Why don't you use import and __import__() ? - They seem designed for such an
application.

I mean, I am not against vicious hacks for the fun of them, but not if they
serve the illusion that what they do can't (easily) be achieved other ways.

Cheers, BB

Peter Waller wrote:
Dear Pythoners,

I know this will probably be perceived as 'evil voodoo', and fair
enough: it probably is. I guess it is unpythonic.

.. but I want to know how to do it anyway - mostly for my own
interest.

Consider the following snippet of code:

---
def Get( *names ):
if not names: return None

frame = sys._getframe(1)
prevFrameLocals = frame.f_locals

for name in names:
prevFrameLocals[ name ] = FetchObjectNamed( name )

Get("a", "b", "c")

print a, b, c
---

FetchObjectNamed() is an arbitrary function which takes a string and
returns an object it got from some store somewhere.

This works fine at the module level, because names in the locals/
globals dictionary can be played with in this way. The idea is to save
lots of typing, i.e.

a, b, c = Get("a","b","c")

..gets frustrating after much typing for many objects with long names.
This is just an example, there are other instances I have where it
would be nice to inject names into the frame above.

Of course, we hit a road block when we call 'Get' from a function
rather than a module, because the locals dictionary does not get
copied back into the code object automatically, so we have to add this
snippet before the Get() function returns:

from ctypes import pythonapi, py_object, c_int
pythonapi.PyFrame_LocalsToFast( py_object( frame ), 1 )

This copies back the names into the code object, and works fine.. that
is, if the names already exist within the code object.

def MyFunction():
a = None
Get("a")
print a # Works
Get("b")
print b # Name error, b is undefined

Is there any way for Get() to define a new variable within
MyFunction's code object? Or is there any programmatic way to, at
runtime, insert new names into functions?

I don't care how hacky it is and whether it requires making calls to
python's internals with ctypes - maybe the whole code object needs to
be replaced? is it even possible to do that when the Get() function is
about to return to this new code object?

Cheers,

- Peter
--
http://mail.python.org/mailman/listinfo/python-list
Sep 13 '08 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
1812
by: Ron_Adam | last post by:
Hi, Sometimes it just helps to see what's going on, so I've been trying to write a tool to examine what names are pointing to what objects in the current scope. This still has some glitches,...
17
6485
by: George Sakkis | last post by:
Is there a general way of injecting code into a function, typically before and/or after the existing code ? I know that for most purposes, an OO solution, such as the template pattern, is a cleaner...
3
2107
by: exolon | last post by:
Yes is it possible to display a layer above an other frame than the one the layer come from ?!? thanks ;)
5
2870
by: Nadav | last post by:
Hi, Introduction: ************************************************************ I am working on a project that should encrypt PE files ( Portable executable ), this require me to inject some...
10
6827
by: Brian W | last post by:
Hi All, I have a web user control that, among other things, provides Print this page, and Email this page functionality I have this script that is to execute on the click of the asp:hyperlinks ...
10
7092
by: John Salerno | last post by:
If I want to have a list like this: where the first part of each tuple is a variable name and the second part is a label for the user to see, such as a form like this: First Name: ________...
9
3506
by: tai | last post by:
Hi. I'm looking for a way to define a function that's only effective inside specified function. Featurewise, here's what I want to do: bar_plugin_func = function() { ...; setTimeout(...);...
5
1729
by: Randy Webb | last post by:
The list below has the current section number, proposed anchor name, and then the current title of that section. Some make sense, some don't. There are a few that don't have proposed anchor names...
14
1757
by: ofiras | last post by:
Hii everyone, I'm a web programmer, but I never understood sql injecting. All I found was that you can write "a' or 'a'='a" in the password field to try to connect without knowing the password. I...
0
7233
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7135
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7410
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
7067
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
5650
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
3215
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3201
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1570
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
440
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.