Accessing global namespace

  • Thread starter =?iso-8859-9?Q?Tongu=E7?= Yumruk
  • Start date
?

=?iso-8859-9?Q?Tongu=E7?= Yumruk

I'm trying to build a completely plug-in based system. One of my
problems is importing a package dynamically. I'm trying to emulate the
import command. The __import__() function or imp module doesn't help me
much because they only return the module. I want to register the module
with it's name in the current namespace. I can do it by:

globals()[module_name] = __import__(module_name)

But I don't think it's a good thing to access the global namespace
directly. I prefer using setattr() but I cannot access the current
namespace as an object I want something like

setattr(__main__,__import__(module_name))

Is that possible? I'm using Python 2.1 on Debian Woody

--
Love, Respect, Linux
############################################################################
"Has anyone had problems with the computer accounts?"
"Yes, I don't have one."
"Okay, you can send mail to one of the tutors ..."
-- E. D'Azevedo, Computer Science 372
############################################################################
Tonguç Yumruk
 
P

Peter Otten

Tonguç Yumruk said:
I'm trying to build a completely plug-in based system. One of my
problems is importing a package dynamically. I'm trying to emulate the
import command. The __import__() function or imp module doesn't help me
much because they only return the module. I want to register the module
with it's name in the current namespace. I can do it by:

globals()[module_name] = __import__(module_name)

But I don't think it's a good thing to access the global namespace
directly. I prefer using setattr() but I cannot access the current
namespace as an object I want something like

setattr(__main__,__import__(module_name))

Is that possible? I'm using Python 2.1 on Debian Woody

Try (tested with 2.2 and 2.3).

import sys

setattr(sys.modules[__name__], "myos", __import__("os"))

sys.modules is a dictionary of all imported modules. It even has a
"__main__" key.

Peter
 
P

Peter Hansen

Tonguç Yumruk said:
I'm trying to build a completely plug-in based system. One of my
problems is importing a package dynamically. I'm trying to emulate the
import command. The __import__() function or imp module doesn't help me
much because they only return the module. I want to register the module
with it's name in the current namespace. I can do it by:

globals()[module_name] = __import__(module_name)

But I don't think it's a good thing to access the global namespace
directly.

There's nothing wrong with "accessing the global namespace directly"
like that. In fact, that's pretty much the only way (though it's not
in itself sufficient) to emulate the "import" statement when you want
a dynamic import.

In general, you need to (a) import with __imoprt__, (b) insert name
into sys.modules dictionary, and (c) insert name into globals(). What
you are doing above is the proper way to do that, IMHO.

-Peter
 
J

John Roth

Tonguç Yumruk said:
I'm trying to build a completely plug-in based system. One of my
problems is importing a package dynamically. I'm trying to emulate the
import command. The __import__() function or imp module doesn't help me
much because they only return the module. I want to register the module
with it's name in the current namespace. I can do it by:

globals()[module_name] = __import__(module_name)

But I don't think it's a good thing to access the global namespace
directly. I prefer using setattr() but I cannot access the current
namespace as an object I want something like

setattr(__main__,__import__(module_name))

Is that possible? I'm using Python 2.1 on Debian Woody

The easiest way to do a dynamic import is to build an
import statement and feed it into the exec statement.

On the other hand, I'd question why you actually want
the name in the global namespace of your module. Might
putting it in some kind of data structure be better for your
program logic? I don't know enough about your application
to tell, though.

John Roth
 
C

Carl Banks

John said:
Tongu? Yumruk said:
I'm trying to build a completely plug-in based system. One of my
problems is importing a package dynamically. I'm trying to emulate the
import command. The __import__() function or imp module doesn't help me
much because they only return the module. I want to register the module
with it's name in the current namespace. I can do it by:

globals()[module_name] = __import__(module_name)

But I don't think it's a good thing to access the global namespace
directly. I prefer using setattr() but I cannot access the current
namespace as an object I want something like

setattr(__main__,__import__(module_name))

Is that possible? I'm using Python 2.1 on Debian Woody

The easiest way to do a dynamic import is to build an
import statement and feed it into the exec statement.


Also, the best way to make your program vulnerable to abuse.

Use exec only if you explicit intend to give the user the option to
input Python code, and only if the program is not running at a higher
privledge level than the user is.


Just use global(); it works exactly as intended; and life is too short
to worry about whether every little line of code is Pythonic.


--
CARL BANKS http://www.aerojockey.com/software

As the newest Lady Turnpot descended into the kitchen wrapped only in
her celery-green dressing gown, her creamy bosom rising and falling
like a temperamental souffle, her tart mouth pursed in distaste, the
sous-chef whispered to the scullery boy, "I don't know what to make of
her."
--Laurel Fortuner, Montendre, France
1992 Bulwer-Lytton Fiction Contest Winner
 
J

John Roth

Carl Banks said:
John said:
Tongu? Yumruk said:
I'm trying to build a completely plug-in based system. One of my
problems is importing a package dynamically. I'm trying to emulate the
import command. The __import__() function or imp module doesn't help me
much because they only return the module. I want to register the module
with it's name in the current namespace. I can do it by:

globals()[module_name] = __import__(module_name)

But I don't think it's a good thing to access the global namespace
directly. I prefer using setattr() but I cannot access the current
namespace as an object I want something like

setattr(__main__,__import__(module_name))

Is that possible? I'm using Python 2.1 on Debian Woody

The easiest way to do a dynamic import is to build an
import statement and feed it into the exec statement.


Also, the best way to make your program vulnerable to abuse.

Use exec only if you explicit intend to give the user the option to
input Python code, and only if the program is not running at a higher
privledge level than the user is.

Now, now. Did I say anything about accepting raw, unvalidated
input from the user? I certainly don't see anything about it in what
I said.

There are pleanty of things I say that you can validly assail me for.
This doesn't happen to be one of them.

John Roth
 
C

Carl Banks

John said:
Carl Banks said:
John said:
I'm trying to build a completely plug-in based system. One of my
problems is importing a package dynamically. I'm trying to emulate the
import command. The __import__() function or imp module doesn't help me
much because they only return the module. I want to register the module
with it's name in the current namespace. I can do it by:

globals()[module_name] = __import__(module_name)

But I don't think it's a good thing to access the global namespace
directly. I prefer using setattr() but I cannot access the current
namespace as an object I want something like

setattr(__main__,__import__(module_name))

Is that possible? I'm using Python 2.1 on Debian Woody

The easiest way to do a dynamic import is to build an
import statement and feed it into the exec statement.


Also, the best way to make your program vulnerable to abuse.

Use exec only if you explicit intend to give the user the option to
input Python code, and only if the program is not running at a higher
privledge level than the user is.

Now, now. Did I say anything about accepting raw, unvalidated
input from the user? I certainly don't see anything about it in what
I said.

There are pleanty of things I say that you can validly assail me for.
This doesn't happen to be one of them.

You said nothing about raw, invaludated input, and that's the problem.
Instead, you swept the potential little pitfall under the rug, and
freely gave your advice to use exec as if one could use it without any
care in the world.

That's not only validly assailable, my friend, but asinine.

I stand by what I said. Using exec for anything other than explicitly
asking the user for Python code is wrong, incorrect, and evil, with
very few exceptions. Even if it looks harmless. Anyone who does
that, or advises that, should be fired.


--
CARL BANKS http://www.aerojockey.com/software

As the newest Lady Turnpot descended into the kitchen wrapped only in
her celery-green dressing gown, her creamy bosom rising and falling
like a temperamental souffle, her tart mouth pursed in distaste, the
sous-chef whispered to the scullery boy, "I don't know what to make of
her."
--Laurel Fortuner, Montendre, France
1992 Bulwer-Lytton Fiction Contest Winner
 
J

John Roth

Carl Banks said:
John said:
Carl Banks said:
John Roth wrote:

I'm trying to build a completely plug-in based system. One of my
problems is importing a package dynamically. I'm trying to emulate the
import command. The __import__() function or imp module doesn't help me
much because they only return the module. I want to register the module
with it's name in the current namespace. I can do it by:

globals()[module_name] = __import__(module_name)

But I don't think it's a good thing to access the global namespace
directly. I prefer using setattr() but I cannot access the current
namespace as an object I want something like

setattr(__main__,__import__(module_name))

Is that possible? I'm using Python 2.1 on Debian Woody

The easiest way to do a dynamic import is to build an
import statement and feed it into the exec statement.


Also, the best way to make your program vulnerable to abuse.

Use exec only if you explicit intend to give the user the option to
input Python code, and only if the program is not running at a higher
privledge level than the user is.

Now, now. Did I say anything about accepting raw, unvalidated
input from the user? I certainly don't see anything about it in what
I said.

There are pleanty of things I say that you can validly assail me for.
This doesn't happen to be one of them.

You said nothing about raw, invaludated input, and that's the problem.
Instead, you swept the potential little pitfall under the rug, and
freely gave your advice to use exec as if one could use it without any
care in the world.

That's not only validly assailable, my friend, but asinine.

I stand by what I said. Using exec for anything other than explicitly
asking the user for Python code is wrong, incorrect, and evil, with
very few exceptions. Even if it looks harmless. Anyone who does
that, or advises that, should be fired.

1. If you call me asinine, I'm not your friend. Apologize, or that stands.

2. One of the fundamental design principles for writing stable
(let alone secure) software is to validate user input. Some people
learn this sooner than others. To say what you said about exec
is simply short sighted. There are too many uses for generating
code internally and then using exec to compile it for that statement
to be anything other than (well, I'm not willing to characterize it
here.) In any case, asking the user for Python code to exec is
the last thing I would do, unless I was writing a command line
interpreter or some such.

2. As far as the pot calling the kettle black, I shouldn't need to
point out to you that using the global() function to stuff random,
unvalidated identifiers into your module namespace can be exploited
by the ungodly. That can, of course, be guarded against by validating
the user input, but then so can using exec.

At this point, I could simply cut and paste your diatribe here,
and have it be a perfectly valid attack on your leading naive
newbies astray. I will, however, let you take that exercise should
you care to do so.

3. My original suggestion was to put the names in some other
data structure rather than in the module namespace. As far
as I know, that's the only secure method of handling it. Of
course, that's kind of swallowing camels while straining at
gnats since the entire objective of the exercise seems to be to
accept entire unvalidated modules into the application.

4. If you want to continue the pissing contest, go right ahead.
I don't particularly care to be known for my command of
intemperate language.

John Roth
 
J

John Roth

Minor note here - because of the latest
spate of worms, etc, everything directed
to this email address is going to my vendor's
equivalent of /dev/null without further
inspection. This has been happening for
the last two weeks, it has nothing to do
with the current unpleasantness.

In other words, anything that needs to be
said on this thread (or any other) needs to
be said on the newsgroup, or remain
unsaid.

John Roth
 
C

Carl Banks

John said:
Minor note here - because of the latest
spate of worms, etc,


Worms--do you mean those annoying little programs that exist because
people have casual attitudes about potentially exploitable programming
flaws?


(I's so sorry, I couldn't resist that--I'm done now--I promise.)
--
CARL BANKS http://www.aerojockey.com/software

As the newest Lady Turnpot descended into the kitchen wrapped only in
her celery-green dressing gown, her creamy bosom rising and falling
like a temperamental souffle, her tart mouth pursed in distaste, the
sous-chef whispered to the scullery boy, "I don't know what to make of
her."
--Laurel Fortuner, Montendre, France
1992 Bulwer-Lytton Fiction Contest Winner
 
J

John Roth

Carl Banks said:
Worms--do you mean those annoying little programs that exist because
people have casual attitudes about potentially exploitable programming
flaws?

Casual? I'd say the persistant use of known insecure programming
languages like C and C++ for the foundations of our systems is
anything but casual. And the design of Windows to make it very
easy to execute unexamined and untrusted code was likewise anything
but casual. One is (arguably) criminal laziness on a lot of people's
parts, and the other was simple arrogance on the part of a known
monopolist.

John Roth
(I's so sorry, I couldn't resist that--I'm done now--I promise.)

I can resist anything - but temptation.
Mark Twain
 
D

Dave Benjamin

Carl said:
> [...snip...]
I stand by what I said. Using exec for anything other than explicitly
asking the user for Python code is wrong, incorrect, and evil, with
very few exceptions. Even if it looks harmless. Anyone who does
that, or advises that, should be fired.

Ought I to be fired for writing something like this?

#!/usr/bin/env python

def attr_reader(name):
return '''\
def get_%s(self):
return self._%s
%s = property(get_%s)
''' % (name, name, name, name)

class Testes:
_a = 42
exec attr_reader('a')

t = Testes()
print t.a

Output: 42

Dave
 
J

Jeff Epler

Carl said:
[...snip...]
I stand by what I said. Using exec for anything other than explicitly
asking the user for Python code is wrong, incorrect, and evil, with
very few exceptions. Even if it looks harmless. Anyone who does
that, or advises that, should be fired.

Ought I to be fired for writing something like this?
[snipped]

I'd say you're better off writing something like this:

def attr_reader(name):
def get(self):
return getattr(self, "_" + name)
return property(get)

class Benjamin(object):
_a = 42
a = attr_reader('a')

t = Benjamin()
print t.a

Jeff
 
J

John Roth

Dave Benjamin said:
Carl said:
[...snip...]
I stand by what I said. Using exec for anything other than explicitly
asking the user for Python code is wrong, incorrect, and evil, with
very few exceptions. Even if it looks harmless. Anyone who does
that, or advises that, should be fired.

Ought I to be fired for writing something like this?

#!/usr/bin/env python

def attr_reader(name):
return '''\
def get_%s(self):
return self._%s
%s = property(get_%s)
''' % (name, name, name, name)

class Testes:
_a = 42
exec attr_reader('a')

t = Testes()
print t.a

Output: 42

Dave

I didn't go through it in detail to check for safety. He was getting
after me for not emphasizing, a couple of exchanges above, that
using exec can be very unsafe unless you either construct the input
yourself, or validate the user input. It's something that's worth
remembering.

John Roth
 
J

Jeff Epler

True, but with the "exec" version, you could implement attr_accessor,
too (getter and setter), as well as write a version that works like this:

def attr_accessor(name, validator):
def get(self):
return getattr(self, "_" + name)

def set(self, value):
setattr(self, "_" + name, value)

return property(get, set)
exec attr_reader('a', 'b', 'c')

def attr_reader_star(*names):
return [attr_reader(name) for name in names]
a, b, c = attr_reader('a', 'b', 'c')

The optimizing compiler, if it was written, should also hoist the
getattr() and setattr() calls to LOAD_ATTR and STORE_ATTR calls:
it will be forbidden to shadow builtins, so the optimizer can replace
getattr() and setattr() with more efficient bytecode sequences if
possible. Second, it can notice that 'name' is immutable and never
rebound. Third, it can notice that "_" + name is also a constant
expresion. Now, the optimizer has enough informtaion to transform the
getattr() expression into a LOAD_ATTR instruction.

Jeff
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top