Is there a way to perform a python import which is not atomic?
For instance, I have a file as follows:
# Filename: a.py
myvariable = 1
mylist = [1, 2, 3]
raise ImportError
donotimportthis = 5
I then have a separate file which does the following:
import a
a.myvariable == 1 # This is okay as it imported it
a.donotimportthis # <-- raise an exception as this is not imported.
I have a file which contains some python code, this follows the format of:
...variables...
import X
I do not have X installed nor do I want it however I do want the variables.
Note: This file is autogenerated not by me but by a tool whose version is frozen.
Two choices, in descending order of preference:
Change the autogeneration process. Instead of invoking proprietary_autogen_process, invoke custom_autogen_wrapper. This wrapper in turn first invokes the proprietary third-party tool, and then modifies the produced module source code by searching for the code that imports module X, and deletes everything after it.
This is relatively straightforward. You just need to take some care to not introduce false positives or false negatives by performing too loose (or too strict) matching of the import code. Ideally you’d use an AST rewriter but that’s probably overkill; a regular expression search for import X might work, although it will yield wrong results if this text appears inside a comment, string literal or inside a method which isn’t executed.
Generate a stub module X in a location where it will be found by the autogenerated module when importing the latter. I don’t recommend this because it’s tedious: You probably can’t just generate an empty module, since the autogenerated module will want to use X. You need to generate meaningful method stubs.
You can do specific imports with
from a import myvariable
EDIT: The above won't work if anything that is flat in the file raises an error. If you have no way to edit the imported file then I don't know if there is a (resonable) solution to this. Sorry didn't realise.
(an unreasonable solution would be to read in the file as text, slice it, and then run eval on it).
Or, as mentioned in the comments, put the stuff you don't want under
if __name__=="__main__":
<here>
Then it will only be invoked if you run the file directly.
What you can do is removing the donotimportthis variable at the end of the module, as follows: del donotimportthis. I hope it helps
Related
I am in the habit of using raw_input(...) for certain debugging. However, in python3 this has changed to input(...). Is there a way to define an alias at the top of my project, such as:
# __init__.py
raw_input = input
I tried the above, but it only worked in the file I added it to, and not any other files in that directory. I'd like this to work basically in every file within my python repository.
You can define all aliases in a separate file (e.g. aliases.py) then import said file where needed (i.e. import aliases).
The con with this method that you'll be referencing the alias through aliases.alias unless you make the import stricter (i.e. from aliases import raw_input) or if you don't care about avoiding a wildcard import (i.e. from aliases import *).
Additionally, if you don't mind another import in the aliases file you can use the builtins namespace:
import builtins
builtins.raw_input = input
You still have to define all aliases separate file (e.g. aliases.py) then import said file where needed (i.e. import aliases) but the advantage of using the builtins namespace is that you can use that import exactly as given.
You can do it by creating a module for creating the renaming function and then importing it to every file you want to like this:
First the module function declaration in alias.py
def raw_input(a):
return input(a)
Secondly, import to another file:
from alias import raw_input
x = raw_input("hello world")
print(x)
Sadly, you will have to make the import of the module to every file you want to use the renamed function.
Hope it works for you!
Put this at the top, and you will get exactly what you want.
import builtins
builtins.raw_input = builtins.input
It is guaranteed to work, but generally considered a bad practice (everybody will be confused with where is that raw_input defined)
If you type this:
import somemodule
help(somemodule)
it will print out paged package description. I would need to get the same description as a string but without importing this package to the current namespace. Is this possible? It surely is, because anything is possible in Python, but what is the most elegant/pythonic way of doing so?
Side note: by elegant way I mean without opening a separate process and capturing its stdout... ;)
In other words, is there a way to peek into a unimported but installed package and get its description? Maybe something with importlib.abc.InspectLoader? But I have no idea how to make it work the way I need.
UPDATE: I need not just not polluting the namespace but also do this without leaving any traces of itself or dependent modules in memory and in sys.modules etc. Like it was never really imported.
UPDATE: Before anyone asks me why I need it - I want to list all installed python packages with their description. But after this I do not want to have them imported in sys.modules nor occupying excessive space in memory because there can be a lots of them.
The reason that you will need to import the module to get a help string is that in many cases, the help strings are actually generated in code. It would be pointlessly difficult to parse the text of such a package to get the string since you would then have to write a small Python interpreter to reconstruct the actual string.
That being said, there are ways of completely deleting a temporarily imported modules based on this answer, which summarizes a thread that appeared on the Python mailing list around 2003: http://web.archive.org/web/20080926094551/http://mail.python.org/pipermail/python-list/2003-December/241654.html. The methods described here will generally only work if the module is not referenced elsewhere. Otherwise the module will be unloaded in the sense that import will reload it from scratch instead of using the existing sys.modules entry, but the module will still live in memory.
Here is a function that does approximately what you want and even prints a warning if the module does not appear to have been unloaded. Unlike the solutions proposed in the linked answer, this function really handles all the side-effects of loading a module, including the fact that importing one package may import other external packages into sys.modules:
import sys, warnings
def get_help(module_name):
modules_copy = sys.modules.copy()
module = __import__(module_name)
h = help(module)
for modname in list(sys.modules):
if modname not in modules_copy:
del sys[modname]
if sys.getrefcount(module) > 1:
warnings.warn('Module {} is likely not to be completely wiped'.format(module_name))
del module
return h
The reason that I make a list of the keys in the final loop is that it is inadvisable to modify a dictionary (or any other iterable) as you iterate through it. At least in Python 3, dict.keys() returns an iterable that is backed by the dictionary itself, not a frozen copy. I am not sure if h = ... and return h are even necessary, but in the worst case, h is just None.
Well, if you are only worried about keeping the global namespace tidy, you could always import in a function:
>>> def get_help():
... import math
... help(math)
...
>>> math
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'math' is not defined
I would suggest a different approach, if i understand you correctly, you wish to read a portion of a package, without importing it (even within a function with local scope). I would suggest a method to do so would be via accessing the (python_path)/Lib/site-packages/(package_name)/ and reading the contents of the respective files as an alternative to importing the module so Python can.
I found the following code snippet that I can't seem to make work for my scenario (or any scenario at all):
def load(code):
# Delete all local variables
globals()['code'] = code
del locals()['code']
# Run the code
exec(globals()['code'])
# Delete any global variables we've added
del globals()['load']
del globals()['code']
# Copy k so we can use it
if 'k' in locals():
globals()['k'] = locals()['k']
del locals()['k']
# Copy the rest of the variables
for k in locals().keys():
globals()[k] = locals()[k]
I created a file called "dynamic_module" and put this code in it, which I then used to try to execute the following code which is a placeholder for some dynamically created string I would like to execute.
import random
import datetime
class MyClass(object):
def main(self, a, b):
r = random.Random(datetime.datetime.now().microsecond)
a = r.randint(a, b)
return a
Then I tried executing the following:
import dynamic_module
dynamic_module.load(code_string)
return_value = dynamic_module.MyClass().main(1,100)
When this runs it should return a random number between 1 and 100. However, I can't seem to get the initial snippet I found to work for even the simplest of code strings. I think part of my confusion in doing this is that I may misunderstand how globals and locals work and therefore how to properly fix the problems I'm encountering. I need the code string to use its own imports and variables and not have access to the ones where it is being run from, which is the reason I am going through this somewhat over-complicated method.
You should not be using the code you found. It is has several big problems, not least that most of it doesn't actually do anything (locals() is a proxy, deleting from it has no effect on the actual locals, it puts any code you execute in the same shared globals, etc.)
Use the accepted answer in that post instead; recast as a function that becomes:
import sys, imp
def load_module_from_string(code, name='dynamic_module')
module = imp.new_module(name)
exec(code, mymodule.__dict__)
return module
then just use that:
dynamic_module = load_module_from_string(code_string)
return_value = dynamic_module.MyClass().main(1, 100)
The function produces a new, clean module object.
In general, this is not how you should dynamically import and use external modules. You should be using __import__ within your function to do this. Here's a simple example that worked for me:
plt = __import__('matplotlib.pyplot', fromlist = ['plt'])
plt.plot(np.arange(5), np.arange(5))
plt.show()
I imagine that for your specific application (loading from code string) it would be much easier to save the dynamically generated code string to a file (in a folder containing an __init__.py file) and then to call it using __import__. Then you could access all variables and functions of the code as parts of the imported module.
Unless I'm missing something?
In my program I have a package filled with various .py files each containing a class definition. I want to make a list where each entry is an instance of one of those classes. In addition, my program doesn't know how many files are in the package or what the files or classes are called, so I can't just import each file. Ideally, I should be able to modify the contents of the package (take out files, put new ones in, etc.) without having to rewrite other parts of the program. Is there a way to do this?
Originally, I had a 'if __name__ == '__main__': return foo()' line in each file and tried to append to the list using execfile(), but obviously this doesn't work. Any ideas?
Sorry if this is kinda vague. I'll try to clarify if needed. I'm using Python 2.5.4.
EDIT:
My program is a random character generator for Dungeons and Dragons. I made a package for every major data type the program needs. I have a package for Classes, Races, Items, etc. and when making a character, my program makes a list of each data type that it can sort through when making a character. For example, when equipping a character, the program can look at the Weapon list and filter out all the weapons that are unsuitable for that character and then randomly choose from the ones that remain.
I don't want to specify file names because I would like the ability to easily add to this program later. If later on down the road I wanted to add more weapon types to the program, I could just write a few new class descriptions and drop them in the Weapons package, and the program could use them without me needing to edit any other code.
This sounds like a bit of a bad design. It would probably be better if you elaborate on the problem and we can help you to solve it some other way. However, what you want isn't hard:
import types
import my_package
my_package_members = [getattr(my_package, i) for i in dir(my_package)]
my_modules = [i for i in my_package_members if type(i) == types.ModuleType]
instances = []
for my_module in my_modules:
my_module_members = [getattr(my_module, i) for i in dir(my_module)]
my_classes = [i for i in my_module_members
if type(i) in (types.TypeType, types.ClassType)]
for my_class in my_classes:
instances.append(my_class())
EDIT: Simplified the code a bit.
To acheive this you are going to need to do the following things:
Have your code enumerate the source files containing your code.
For each source file, import the code specified in the file into a new module.
For each module, locate all the classes contained, instantiate each one and add it to your final list.
To take each part in turn:
To enumerate the source files, use os.walk and os.path to find the files and build full paths to the source.
To import code from a given source file dynamically, you can do execfile(my_file) in my_dict where my_file is the full path to your source file and my_dict is a dictionary to return the resulting code in (any classes declared in the source file would become members of this dict for example). Note you only need to use this method if the files you are importing are not part of a valid python module/package hierarchy (with an init.py file in the package) - if they are you can use import() instead.
To enumerate the classes declared in a given module you could use inspect.getmembers().
If you're willing to do a bit more work, you can use pkg_resource's entry points to advertise and discover the relevant classes. The Fedora Account System uses this to provide plugin functionality.
Assuming, first, that all your modules exist as .py files in the package's directory:
import inspect, glob, os, sys
def thelistyouwant(pathtothepackage):
sys.path.insert(0, pathtothepackage)
result = []
for fn in glob.glob(os.path.join(pathtothepackage, '*.py')):
if fn.startswith('_'): continue # no __init__ or other private modules
m = __import__(fn[:-3])
classes = inspect.getmembers(m, inspect.isclass)
if len(classes) != 1:
print>>sys.stderr, "Skipping %s (%d != 1 classes!)" % (fn, len(classes))
continue
n, c = classes[0]
try:
result.append(c())
except TypeError:
print>>sys.stderr, "Skipping %s, can't build a %s()" % (fn, n)
del sys.path[0]
return result
Further assumptions: each module should have exactly 1 class (otherwise it's skipped with a warning) instantiable without arguments (ditto ditto); you don't want to look at __init__.py (if any; actually this code does not require the path to be an actual package, any directory will do, so __init__.py may or may not be present) nor any module whose name starts with an underscore ("private" modules of the package).
I would like to load a .py file at runtime. This .py file is basically a config file with the following format:
var1=value
var2=value
predicate_function=func line : <return true or false>
Once this file is loaded, I would like to be able to access var1, var2 and predicate_function. For each line, I'll pass it to the predicate function, and if it returns false, I'll ignore it.
In any case, I'm not sure how to load a python file at runtime and access its variables.
Clarification: there may be any number of these config files that I need to pass to the main program and I won't know their names until runtime. Google tells me I should use __import__. I'm not sure how to correctly use that method and then access the variables of the imported file.
As written in the python official documentation, if you just want to import a module by name, you can look it up in the sys.modules dictionary after using __import__.
Supposing your configuration is in myproject.mymodule, you would do like that :
module_name = 'myproject.mymodule'
import sys
__import__(module_name)
mymodule = sys.modules[module_name]
# Then you can just access your variables and functions
print mymodule.var1
print mymodule.var2
# etc...
You can also use the return value of __import__ statement but you will have to understand fully how python works with namespaces and scopes.
You just need to be able to dynamically specify the imports and then dynamically get at the variables.
Let's say your config file is bar.py and looks like this:
x = 3
y = 4
def f(x): return (x<4)
Then your code should look like this:
import sys
# somehow modnames should be a list of strings that are the names of config files
#
# you can do this more dynamically depending on what you're doing
modnames = ['bar']
for modname in modnames:
exec('import %s' % modname)
for modname in modnames:
mod = sys.modules[modname]
for k in mod.__dict__:
if k[:2] != '__':
print modname, k, mod.__dict__[k]
I get this output:
bar f <function f at 0x7f2354eb4cf8>
bar x 3
bar y 4
Then you at least have all the variables and functions. I didn't quite get what you wanted from the predicate functions, but maybe you can get that on your own now.
To access another Python module, you import it. execfile has been mentioned by a couple people, but it is messy and dangerous. execfile clutters your namespace, possibly even messing up the code you are running. When you want to access another Python source file, use the import statement.
Even better would be not to use a Python file for configuration at all, but rather to use the builtin module ConfigParser or a serialization format like JSON. This way your configuration files don't allow execution of arbitrary (possibly malicious) code, doesn't require people to know Python to configure your program, and can easily be altered programatically.
If the imported module is on the regular search path, you can use __import__.
If you need to load the module from an arbitrary path in the filesystem, use imp.load_module.
Be sure to consider the security implications of loading arbitrary user-specified code.
In Python 2.*, execfile works (I recommend passing a specific dictionary and accessing the variables from there -- as the note in the docs says, execfile can't affect the calling function's locals() dictionary).
In Python 3.*, execfile has been removed, so do, instead:
with open('thefile.py') as f:
exec(f.read(), somedict)
Since the Python version hasn't been clearly mentioned, it is worth pointing out that the imp module has been deprecated in newer Python versions in favor of the importlib module. Example here.
I'm kinda late to the party, but I want to present an alternative answer nonetheless.
If you want to import code without affecting the global module namespace, you can create an anonymous module (using types.ModuleType) and load arbitrary code in it (using compile and exec). For instance, like this:
import types
filename = "/path/to/your/file.py"
with open(filename) as fp:
code = compile(fp.read(), filename, "exec")
config_module = types.ModuleType("<config>")
exec code in config_module.__dict__
You can then access the variables as config_module.var1, &c.
If you want to have a configuration file that will only be edited by the user when the program isn't running, just import it as a normal python file
ie.
main.py:
import config
print config.var1
config.py:
var="var12"
var2 = 100.5
try the imp module : http://docs.python.org/library/imp.html