from spam import eggs, spam at runtime, how?

Discussion in 'Python' started by Rene Pijlman, Dec 8, 2003.

  1. Rene Pijlman

    Rene Pijlman Guest

    How do I do:

    from spam import eggs

    .... when 'spam' is only known at runtime?

    --
    René Pijlman
     
    Rene Pijlman, Dec 8, 2003
    #1
    1. Advertising

  2. Rene Pijlman

    Aahz Guest

    In article <>,
    Rene Pijlman <> wrote:
    >
    >How do I do:
    > from spam import eggs
    >... when 'spam' is only known at runtime?


    spam = __import__('spam')
    eggs = spam.eggs
    --
    Aahz () <*> http://www.pythoncraft.com/

    Weinberg's Second Law: If builders built buildings the way programmers wrote
    programs, then the first woodpecker that came along would destroy civilization.
     
    Aahz, Dec 8, 2003
    #2
    1. Advertising

  3. Rene> How do I do:
    Rene> from spam import eggs

    Rene> ... when 'spam' is only known at runtime?

    help(__import__)

    Skip
     
    Skip Montanaro, Dec 8, 2003
    #3
  4. Rene Pijlman

    Rene Pijlman Guest

    Aahz:

    >In article <>,
    >Rene Pijlman <> wrote:
    >>
    >>How do I do:
    >> from spam import eggs
    >>... when 'spam' is only known at runtime?

    >
    >spam = __import__('spam')
    >eggs = spam.eggs


    Hmm... my spam is a package and eggs is a module. This code gives me:

    AttributeError: 'spam' module has no attribute 'eggs'

    But it works like this:

    spam = __import__('spam',globals(),locals(),['eggs'])
    eggs = spam.eggs

    Thanks for putting me on track. Skip to.

    --
    René Pijlman
     
    Rene Pijlman, Dec 8, 2003
    #4
  5. Rene Pijlman wrote:

    > Hmm... my spam is a package and eggs is a module. This code gives me:
    >
    > AttributeError: 'spam' module has no attribute 'eggs'
    >
    > But it works like this:
    >
    > spam = __import__('spam',globals(),locals(),['eggs'])
    > eggs = spam.eggs


    or:

    spam = __import__('spam.eggs')
    eggs = spam.eggs

    </F>
     
    Fredrik Lundh, Dec 8, 2003
    #5
  6. Rene Pijlman

    Rene Pijlman Guest

    Fredrik Lundh:
    >Rene Pijlman:
    >> But it works like this:
    >>
    >> spam = __import__('spam',globals(),locals(),['eggs'])
    >> eggs = spam.eggs

    >
    >or:
    >
    > spam = __import__('spam.eggs')
    > eggs = spam.eggs


    Yes, and a bit more elegant (pythonic?). Thanks.

    --
    René Pijlman
     
    Rene Pijlman, Dec 8, 2003
    #6
  7. Rene Pijlman

    Paul Rubin Guest

    Rene Pijlman <> writes:
    > > spam = __import__('spam.eggs')
    > > eggs = spam.eggs

    >
    > Yes, and a bit more elegant (pythonic?). Thanks.


    Another way:

    exec 'import spam'
     
    Paul Rubin, Dec 8, 2003
    #7
  8. Rene Pijlman

    Aahz Guest

    In article <>,
    Paul Rubin <http://> wrote:
    >
    >Another way:
    >
    > exec 'import spam'


    That's precisely what we were trying to avoid.
    --
    Aahz () <*> http://www.pythoncraft.com/

    Weinberg's Second Law: If builders built buildings the way programmers wrote
    programs, then the first woodpecker that came along would destroy civilization.
     
    Aahz, Dec 8, 2003
    #8
  9. Rene Pijlman

    Paul Rubin Guest

    (Aahz) writes:
    > >Another way:
    > >
    > > exec 'import spam'

    >
    > That's precisely what we were trying to avoid.


    I missed that part. The alternatives don't really seem better though.
     
    Paul Rubin, Dec 8, 2003
    #9
  10. Rene Pijlman

    Ganesan R Guest

    >>>>> "Fredrik" == Fredrik Lundh <> writes:

    > spam = __import__('spam.eggs')
    > eggs = spam.eggs


    Is there a way to do this if I don't know about "eggs" beforehand. I have
    some code which needs to import a DB module dynamically. The module could be
    'PyPgSQL.PgSQL' or 'sqlite'. Is there a sane way to do this without exec?

    Ganesan

    --
    Ganesan R
     
    Ganesan R, Dec 9, 2003
    #10
  11. Rene Pijlman

    Ganesan R Guest

    >>>>> "Ganesan" == Ganesan R <> writes:

    >>>>> "Fredrik" == Fredrik Lundh <> writes:

    >> spam = __import__('spam.eggs')
    >> eggs = spam.eggs


    > Is there a way to do this if I don't know about "eggs" beforehand. I have
    > some code which needs to import a DB module dynamically. The module could be
    > 'PyPgSQL.PgSQL' or 'sqlite'. Is there a sane way to do this without exec?


    db = __import__(dbname, globals(), locals(), ["connect"]) works. The last
    argument just needs to be a non-empty list. __import__ does not seem to do
    anything with it.

    Ganesan

    --
    Ganesan R
     
    Ganesan R, Dec 9, 2003
    #11
  12. "Ganesan R" wrote:
    >
    > > spam = __import__('spam.eggs')
    > > eggs = spam.eggs

    >
    > Is there a way to do this if I don't know about "eggs" beforehand. I have
    > some code which needs to import a DB module dynamically. The module could be
    > 'PyPgSQL.PgSQL' or 'sqlite'. Is there a sane way to do this without exec?


    here's one way to do it:

    dbapi = __import__(dbname)
    for p in name.split(".")[1:]:
    dbapi = getattr(dbapi, p)

    notes:

    - when given a package, __import__ imports all components, but
    returns a reference to the toplevel module).

    - you may still need DB-specific code to connect to the database

    </F>
     
    Fredrik Lundh, Dec 9, 2003
    #12
  13. Rene Pijlman

    John J. Lee Guest

    Rene Pijlman <> writes:

    > How do I do:
    >
    > from spam import eggs
    >
    > ... when 'spam' is only known at runtime?


    Why not just stick the import statement where you need it?

    def do_something_that_needs_spam_module():
    import spam
    ...


    John
     
    John J. Lee, Dec 9, 2003
    #13
  14. Rene Pijlman

    Rene Pijlman Guest

    John J. Lee:
    >Rene Pijlman:
    >> How do I do:
    >>
    >> from spam import eggs
    >>
    >> ... when 'spam' is only known at runtime?

    >
    >Why not just stick the import statement where you need it?


    Because I need a module from one of a number of different packages, at one
    specific point in my code.

    The modules are Cheetah templates (http://www.cheetahtemplate.org/) in
    different skins of a website. I've made one package per skin, and my
    website generator basically does:

    from skin import template

    where skin is only known at runtime (it's passed as a parameter or hidden
    field to my mod_python application).

    The alternative would be:

    if skin == 'basic':
    from basic import homepage
    elif skin == 'modern':
    from modern import homepage

    .... but this is unmaintainable and unpythonic.

    --
    René Pijlman
     
    Rene Pijlman, Dec 9, 2003
    #14
  15. Rene Pijlman

    Paul Rubin Guest

    Rene Pijlman <> writes:
    > >Why not just stick the import statement where you need it?

    >
    > Because I need a module from one of a number of different packages, at one
    > specific point in my code.


    I still don't understand why you don't want to use an exec statement
    for this. That's by far the most natural and understandable way to do it.
     
    Paul Rubin, Dec 9, 2003
    #15
  16. Rene Pijlman

    Peter Hansen Guest

    Paul Rubin wrote:
    >
    > Rene Pijlman <> writes:
    > > >Why not just stick the import statement where you need it?

    > >
    > > Because I need a module from one of a number of different packages, at one
    > > specific point in my code.

    >
    > I still don't understand why you don't want to use an exec statement
    > for this. That's by far the most natural and understandable way to do it.


    In this case, he's getting the actual string from the web, so I wouldn't
    be surprised if exec would be a real can of security worms.

    -Peter
     
    Peter Hansen, Dec 9, 2003
    #16
  17. Rene Pijlman

    Peter Hansen Guest

    Rene Pijlman wrote:
    > The modules are Cheetah templates (http://www.cheetahtemplate.org/) in
    > different skins of a website. I've made one package per skin, and my
    > website generator basically does:
    >
    > from skin import template
    >
    > where skin is only known at runtime (it's passed as a parameter or hidden
    > field to my mod_python application).
    >
    > The alternative would be:
    >
    > if skin == 'basic':
    > from basic import homepage
    > elif skin == 'modern':
    > from modern import homepage
    >
    > ... but this is unmaintainable and unpythonic.


    Unmaintainable as-is, perhaps, but pythonicism has nothing to do with this.

    What is probably cleaner *and* more maintainable is to have an extra level
    of indirection, with some kind of configuration file that in effect maps
    between the skin names and the Python package which implements it. I'd
    personally do this with a quick bit of XML, but I've been drinking too
    much Koolaid(tm) so ignore me.

    The problem I see with the above approach is that you are tying some
    strings that are used in your HTML pages directly to the names of Python
    modules. Unless you are doing this in an entirely automated fashion
    (e.g. generating the list of available skins via a directory scan) then
    you are increasing the coupling in your system inappropriately, and
    *that* is certain to be the least maintainable approach of all, IMHO.

    -Peter
     
    Peter Hansen, Dec 9, 2003
    #17
  18. Rene Pijlman

    Just Guest

    In article <>,
    Peter Hansen <> wrote:

    > Paul Rubin wrote:
    > >
    > > Rene Pijlman <> writes:
    > > > >Why not just stick the import statement where you need it?
    > > >
    > > > Because I need a module from one of a number of different packages, at one
    > > > specific point in my code.

    > >
    > > I still don't understand why you don't want to use an exec statement
    > > for this. That's by far the most natural and understandable way to do it.

    >
    > In this case, he's getting the actual string from the web, so I wouldn't
    > be surprised if exec would be a real can of security worms.


    Also, __import__ returns a module object, so you don't have to pull it
    out of the globals you passed to exec. Compare:

    g = {}
    exec "import %s" % modulename in d
    m = g[modulename]

    with

    m = __import__(modulename)

    Just
     
    Just, Dec 9, 2003
    #18
  19. Rene Pijlman

    Paul Rubin Guest

    Just <> writes:
    > > In this case, he's getting the actual string from the web, so I wouldn't
    > > be surprised if exec would be a real can of security worms.


    Yuch. Although, the string can be checked against the list of available
    modules before exec'ing.

    > Also, __import__ returns a module object, so you don't have to pull it
    > out of the globals you passed to exec. Compare:
    >
    > g = {}
    > exec "import %s" % modulename in d
    > m = g[modulename]


    I think I'd have used

    exec "import %s as mymod"% modulename

    > with
    > m = __import__(modulename)


    OK, that's not as ugly as some of the other stuff I've seen going by.
    I guess it's better than an exec, if you can now just say m.whatever.
     
    Paul Rubin, Dec 9, 2003
    #19
  20. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1


    On 10/12/2003, at 6:28 AM, Rene Pijlman wrote:

    > from skin import template
    >
    > where skin is only known at runtime (it's passed as a parameter or
    > hidden
    > field to my mod_python application).


    That is scary - you need to treat anything arriving from the client
    as an attack. Consider what would happen if someone accessed the url:
    http://whatever/myapp?skin=test.testall

    Maintaining a blacklist is impossible, as new modules may be installed
    in the future.

    > The alternative would be:
    >
    > if skin == 'basic':
    > from basic import homepage
    > elif skin == 'modern':
    > from modern import homepage
    >
    > ... but this is unmaintainable and unpythonic.


    It is also correct IMHO, although you would be better off
    using a dictionary mapping string -> module, so you could just do:

    try:
    homepage = skinmod[skin]
    except KeyError:
    raise ValueError, 'No such skin: %r' % (skin,)

    You may want to use the import tricks elsewhere in this thread to
    build this dictionary though, for instance by doing an os.listdir() on
    your 'skins' directory.


    - --
    Stuart Bishop <>
    http://www.stuartbishop.net/
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.3 (Darwin)

    iD8DBQE/1nZaAfqZj7rGN0oRAlxqAJ4kf+Dm2BBkEhKJpIpokWAxhDPSLACePJlJ
    PKgunqahsWAYzuCHmcvXoxo=
    =bKfh
    -----END PGP SIGNATURE-----
     
    Stuart Bishop, Dec 10, 2003
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    9
    Views:
    481
    Paul Boddie
    Jan 4, 2006
  2. Sergio Correia
    Replies:
    7
    Views:
    298
    Ben Finney
    Sep 18, 2007
  3. Replies:
    3
    Views:
    525
  4. zax75
    Replies:
    1
    Views:
    1,109
  5. David Binnie
    Replies:
    2
    Views:
    453
    Rich Webb
    May 22, 2009
Loading...

Share This Page