25

I have a need to add module attributes at run time. For example, when a module is loaded, it reads the file where the data is contained. I would like that data to be available as a module attribute, but the data is only available at run time.

How can I add module attributes at run time?

jlconlin
  • 14,206
  • 22
  • 72
  • 105

7 Answers7

41

Thanks @Dharmesh. That was what I needed. There is only one change that needs to be made. The module won't be importing itself so to get the module object I can do:

setattr(sys.modules[__name__], 'attr1', 'attr1')

jlconlin
  • 14,206
  • 22
  • 72
  • 105
18

If you don't know the attribute name until runtime, use setattr:

>>> import mymodule
>>> setattr(mymodule, 'point', (1.0, 4.0))
>>> mymodule.point
(1.0, 4.0)
Jeff Bauer
  • 13,890
  • 9
  • 51
  • 73
5

A module attribute is a variable in the module global scope.

if you want to set an attribute from the module itself 'at runtime' the correct way is

globals()['name'] = value

(Note: this approach only works for globals, not for locals.)

if you want to set an attribute from the scope where the module has been imported just set it:

import myModule
setattr(myModule, 'name', 10)

Complete example:

#m.py
def setGlobal(name, value):
    globals()[name] = value

--

#main.py
import m

m.setGlobal('foo', 10)
print(m.foo) #--> 10

#Moreover:

from m import foo
print(foo) #--> 10   (as Expected)

m.setGlobal('foo', 20)
print(m.foo) #--> 20  (also as expected)

#But:
print(foo) #--> 10
angeldeluz777
  • 319
  • 3
  • 4
4

Create dynamic class 'Module' and add attributes dynamically using dictionary like :

attributes = {'attr1': 'attr1', 'attr2': 'attr2'}
module = type('Module', (), attributes)

OR Create only dynamic class 'Module'

module = type('Module', (), {})

and add attribute with setattr method like this:

setattr(module, 'attr3', 'attr3')

OR

import module
setattr(module, 'attr1', 'attr1')
1

Just set it.

my_object = MyObject()
my_object.my_custom_attribute = 'my_value'
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • This works great if you know "my_custom_attribute", but I don't know what it is until run time. – jlconlin Mar 18 '11 at 16:56
  • You don't know the value, or the key? If it's the value, you can do the above at runtime just as well any other. If it's the key, just use `setattr(my_object, my_key, 'my_value')`. – Daniel Roseman Mar 18 '11 at 17:09
  • @Jeremy: How are importers of your module going to know the name of "my_custom_attribute"? In other words, how will they access its value? – martineau Mar 18 '11 at 17:45
  • @martineau Those who will be using my module will know what to expect based on the context. Of course, I will also provide information in the documentation for the module. – jlconlin Mar 18 '11 at 17:48
  • @Jeremy, @martineau: "know what to expect based on the context" smells rather iffy to me. Seems to need a lot of if/elif*/else code in each caller. – John Machin Mar 18 '11 at 18:27
  • @Jeremy: In that case, you'll need to do a `setattr()` as @Jeff Bauer suggested in his answer (and @Daniel Roseman mentions in his comment). A possible alternative would be to provide a predefined module method that accepts the attribute name as argument and returns its value (or something similar). – martineau Mar 18 '11 at 18:30
  • @John Machin: Not necessarily...perhaps some try/except blocks (which should probably be there anyway). – martineau Mar 18 '11 at 18:44
0

Add it as a key to the object's internal dictionary __dict__

my_object.__dict__['newattribute'] = 'attributevalue'
Nikhil M Jain
  • 31
  • 1
  • 2
-7

The global scope of a module is the module itself, so just set a global.

# module.py
a = 1

# script.py
import module
print module.a
# 1
Glenn Maynard
  • 55,829
  • 10
  • 121
  • 131
  • 2
    -1: The question was about adding an attribute at *runtime*. This doesn't answer that question. – Jaap Versteegh May 23 '13 at 20:40
  • @SlashV: This *is* done at runtime. When else do you think you would do this? (Congratulations on announcing an incorrect downvote.) – Glenn Maynard May 28 '13 at 18:44
  • 2
    No need to be rude. Please explain where the runtime bit is. As in: module.py doesn't have "a" after being imported and "a" is added to module.py's dictionary afterwards i.e. 'during runtime'. That's how I understood "runtime" in this question. Feel free to explain if you think I misunderstood that. – Jaap Versteegh May 29 '13 at 22:41
  • @SlashV: I'm not being rude; if you proudly announce downvotes and they're in error, people will tell you so. "a = 1" is a statement which is performed at runtime, setting the global variable "a" to the value 1, which is then available as an attribute on the module object. You can set globals at any time in Python, which will cause them to show up as attributes on the module object (and vice versa). It sounds like you think "a = 1" happens statically, like a C static initializer, but Python doesn't work that way. Even function declarations happen at runtime. – Glenn Maynard May 30 '13 at 21:58
  • 1
    Thanks for explaining to me how python works, but the original question explicitly states that the author doesn't *know* the name of the attribute at the time he is writing the module, so your response just doesn't *answer* the question. Period. You can talk as long as you like and discuss what runtime means and whatever, but at the end of the day you'll have to admit that you didn't answer the question and that my downvote was thus correct. You can "congratulate" me and say that I "proudly announce" things, which is all just rubbish to avoid facing the fact that you're just wrong here! – Jaap Versteegh Jun 01 '13 at 11:16
  • (But for anyone else: the question was about the *data*, eg. value, not being available until runtime. It said nothing about the *name* of the attribute.) – Glenn Maynard Jun 03 '13 at 14:57
  • 1
    Though that is admittedly more trivial, your example *also* doesn't demonstrate setting the *data* of the attribute when that data is unknown at the time of writing of the module. (btw. all the off topic/ugly stuff in this conversation is yours) – Jaap Versteegh Jun 11 '13 at 23:02