views:

401

answers:

7

I would like to load a .py file at runtime. This .py file is basically a config file of the following format: var1=value
var2=value
predicate_function=func line :
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 func, 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 edit: There may be any number of these config files I need to pass to the main program and I won't know their names until runtime. Google tells me I should use "_ _ import _ _," (without spaces between underscores). I'm not sure how to correctly use that method and then access the variables of the imported file.

A: 

execfile

S.Lott
+2  A: 

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
Simon Callan
I may have any number of such config files, so I can't just do an "import configFile." Otherwise this would be the simplest solution :)
Shahbaz
+2  A: 

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)
Alex Martelli
+3  A: 

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.

Mike Graham
Actually the reason I am making my config a python file is because I want the config file to contain a couple of (predicate) functions. Otherwise I would simple read in a text file, split the strings and read into a dict.
Shahbaz
+1  A: 

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.

oefe
A: 

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.

forefinger
Worked perfectly, thanks forefinger!
Shahbaz
+1  A: 

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.

Clément
`__import__` already returns the module object, you don't have to later get it from `sys.modules`.
Mike Graham
mmh, nope, in my example, it would return `myproject` module and not `myproject.mymodule`. Straight from the doc :_When the name variable is of the form package.module, normally, the top-level package (the name up till the first dot) is returned, not the module named by name._
Clément