Customize compile function in python? - python

RestrictedPython module has a restricted compiler in which you can compile code and customize some python features. For example, you can replace the builtin print function.
That's what I need to do. I need to compile some code but defining my own print function. I can't use this restricted compiler because it has a lot of restrictions I don't need at now.
Do you know any other compiler in which I can define my own print function?

Just use regular Python then; in Python 2 use:
from __future__ import print_function
or use Python 3, and print() is then a function. You can redefine that function:
from __future__ import print_function
try:
# Python 2
from __builtin__ import print as builtin_print
except ImportError:
from builtins import print as builtin_print
def print(*args, **kw):
# do something extra with *args or **kw, etc.
builtin_print(*args, **kw)
Like any other built-in function you can define your own function using the same name. In the above example I used the __builtin__ / builtins module to access the original.
If you are using exec(), you can pass in the print() function you defined as an extra name in the namespace you pass in:
exec(code_to_execute, {'print': your_print_function})
For Python 2, you do need to compile the code first to switch off the print statement and enable the print() function; use the compile() function to produce a code object to pass to the exec statement:
import __future__
code_to_execute = compile(
code_to_execute_in_string, '', 'exec',
flags=__future__.print_function.compiler_flag)
I used the __future__ module to obtain the right compiler flag.

Related

Python3 dynamic import with exec - why does 'as' not be executed?

I have this code that carry module manually
exec("import" + moduleName + " as selectedModule")
importlib.reload(selectedModule)
But this code make
name 'seletedModule' is not defined
It is not happened on python2.x.
How to import this on python3?
If you need to import a library dynamically, don't use exec, its not safe.
Use importlib.import_module instead.
selected_module = importlib.import_module(module_name)
importlib.reload(selected_module)
As for the error you're getting: you're probably calling exec within a function scope, thus you'll need you manually set globals and locals to be the same in exec (Using a function defined in an exec'ed string in Python 3). Workaround:
exec("<do-stuff>", globals())

Module namespace initialisation before execution

I'm trying to dynamically update code during runtime by reloading modules using importlib.reload. However, I need a specific module variable to be set before the module's code is executed. I could easily set it as an attribute after reloading but each module would have already executed its code (e.g., defined its default arguments).
A simple example:
# module.py
def do():
try:
print(a)
except NameError:
print('failed')
# main.py
import module
module.do() # prints failed
module.a = 'succeeded'
module.do() # prints succeeded
The desired pseudocode:
import_module_without_executing_code module
module.initialise(a = 'succeeded')
module.do()
Is there a way to control module namespace initialisation (like with classes using metaclasses)?
It's not usually a good idea to use reload other than for interactive debugging. For example, it can easily create situations where two objects of type module.A are not the same type.
What you want is execfile. Pass a globals dictionary (you don't need an explicit locals dictionary) to keep each execution isolated; anything you store in it ahead of time acts exactly like the "pre-set" variables you want. If you do want to have a "real" module interface change, you can have a wrapper module that calls (or just holds as an attribute) the most recently loaded function from your changing file.
Of course, since you're using Python 3, you'll have to use one of the replacements for execfile.
Strictly speaking, I don't believe there is a way to do what you're describing in Python natively. However, assuming you own the module you're trying to import, a common approach with Python modules that need some initializing input is to use an init function.
If all you need is some internal variables to be set, like a in you example above, that's easy: just declare some module-global variables and set them in your init function:
Demo: https://repl.it/MyK0
Module:
## mymodule.py
a = None
def do():
print(a)
def init(_a):
global a
a = _a
Main:
## main.py
import mymodule
mymodule.init(123)
mymodule.do()
mymodule.init('foo')
mymodule.do()
Output:
123
foo
Where things can get trickier is if you need to actually redefine some functions because some dynamic internal something is dependent on the input you give. Here's one solution, borrowed from https://stackoverflow.com/a/1676860. Basically, the idea is to grab a reference to the current module by using the magic variable __name__ to index into the system module dictionary, sys.modules, and then define or overwrite the functions that need it. We can define the functions locally as inner functions, then add them to the module:
Demo: https://repl.it/MyHT/2
Module:
## mymodule.py
import sys
def init(a):
current_module = sys.modules[__name__]
def _do():
try:
print(a)
except NameError:
print('failed')
current_module.do = _do

from past import print_statement

Is there some equivalent to from __future__ import print_function that forward-ports the print statement from python 2.x?
An answer involving some ipython magic that lets me print without need of surrounding parens during prototyping is also acceptable.
Some suggestion for IPython
%autocall
print "Hi"
Define magic with autocall on
from IPython.core.magic import register_line_magic
#register_line_magic
def p(line):
print(line)
p "Hi"
Define magic with autocall off
from IPython.core.magic import register_line_magic
#register_line_magic
def p(line):
print(eval(line))
%p "Again"
You could create a .config/ipython/profile_default/startup/autoprint.py file for you line magic functions.
Provisional answer (A solution that doesn't involve a leading / will be preferred.): IPython automatically calls an object if line begins with a /, even if it's indented:
def f():
/print 'foo'
f()
prints foo.
Edit:
IPython also has an %autocall magic function that, well, automatically calls functions, so after doing %autocall 1, typing print 3 in a cell acts like print in python 2.x (though this unfortunately doesn't work in function definitions like / does.
Also, since it's a function and not a statement, you can simply do p = print, so later /p 'foo' calls give you almost pdb-like behavior (something I was going for but that wasn't explicitly stated in the question).

How to make print() override work "globally"

From How to override python builtins with an import statement I obtained the following code:
from __future__ import print_function
def print(*args, **kwargs):
.
. some intervening logic
.
return __builtins__.print(*args, **kwargs)
This code works fine, but has module scope. That is, if there are print statements within this file they work as expected, going through the print() function as defined. However, importing it (from foo import *) has no effect within the module that imported it.
If I want to override the print function "globally" how is this best done. Ideally:
from MyOverrides import *
.
.
.
class foo():
.
.
def bar( self ):
print( "this is my overridden print statement" )
What am I missing about future, overrides, and print() here?
My environment is 2.6 and forward, but not 3.0.
You can't (and shouldn't) have a global override that turns on a future statement. Since future statements affect the way a Python source file is parsed and compiled, before Python can even tell that MyOverrides defines a print function, all future statements a module uses must be explicit. You can't import a future statement from another module.
The safest way to replace the print function is to explicitly use from __future__ import print_function in all your modules, then import a replacement for print from one of your modules. Don't replace __builtin__.print.
If you want to affect all output to stdout, whether by print statement or print function, anywhere at all, you can replace sys.stdout with a wrapper.
import sys
stdout = sys.stdout
class new_stdout(object):
def write(*args, **kwargs):
# do whatever
stdout.write(*args, **kwargs)
sys.stdout = new_stdout()
However, this is probably a bad idea, and it won't affect print statements or print functions that use an explicit file argument.
Another stackoverflow user provided most of the answer, but then apparently deleted it (?). Here is a working solution. Once again, I recognize this isn't necessarily a best practice, but it can be handy in certain situations.
Module MyOverrides.py:
from __future__ import print_function
import __builtin__
builtin_print = __builtin__.print
def print(*args, **kwargs):
.
.... whatever code you need here
.
return builtin_print(*args, **kwargs)
__builtin__.print = print
Module test.py:
from __future__ import print_function
from MyOverrides import *
.
.
.
As pointed out by another user, future import needs to happen in every module that intends to use future functionality.
Thanks to user #kindall who answered and then apparently withdrew the answer.

Injecting Locals into Dynamically Loaded Modules Before Execution

I'm trying to build a sort of script system in python that will allow small snippets of code to be selected and executed at runtime inside python.
Essentially I want to be able to load a small python file like
for i in Foo: #not in a function.
print i
Where somewhere else in the program I assign what Foo will be. As if Foo served as a function argument to the entire loaded python file instead of a single function
So somewhere else
FooToPass = GetAFoo ()
TempModule = __import__ ("TheSnippit",<Somehow put {'Foo' : FooToPass} in the locals>)
It is considered bad style to have code with side effects at module level. If you want your module to do something, put that code in a function, make Foo a parameter of this function and call it with the desired value.
Python's import mechanism does not allow to preinitialise a module namespace. If you want to do this anyway (which is, in my opinion, confusing and unnecessary), you have to fiddle around with details of the import mechanism. Example implementation (untested):
import imp
import sys
def my_import(module_name, globals):
if module_name in sys.modules:
return sys.modules[module_name]
module = imp.new_module(module_name)
vars(module).update(globals)
f, module.__file__, options = imp.find_module(module_name)
exec f.read() in vars(module)
f.close()
sys.modules[module_name] = module
return module

Categories