36 views
Skip to first unread message

Boštjan Mejak

unread,
Jul 21, 2015, 1:54:22 PM7/21/15
to wxPython Help
def tryToImport(module):

    try:
        import module

    except ImportError:
        print("The import failed.")


As you can see from my code above, the function tryToImport() takes a 'module' argument which is then taken as a module to be imported. But I always get "The import failed." message. Why does my code not work? No module can be imported this way, even the built-in Python modules. How can I refactor my code to make this work?

Werner

unread,
Jul 21, 2015, 2:15:11 PM7/21/15
to wxpytho...@googlegroups.com
maybe using python's importlib

Werner

Boštjan Mejak

unread,
Jul 21, 2015, 4:41:06 PM7/21/15
to wxPython Help
I was thinking something along the same lines. What about, instead of using the importlib, doing __import__(module)?

Boštjan Mejak

unread,
Jul 21, 2015, 4:53:34 PM7/21/15
to wxPython Help
My suggestion works like a charm. But one refinement is needed: __import__("module"). The argument, i.e. the name of the module to be imported, needs to be enclosed in parentheses.

But now I am baffled. Why  import module  doesn't work and  __import__("module")  does work? What is the difference here?

Boštjan Mejak

unread,
Jul 21, 2015, 5:02:52 PM7/21/15
to wxPython Help
Oops, forget what I said about "enclosed in parentheses". No parentheses needed. My bad.

So, anyway, why is the attempt with the  import  statement not working and is working by using the  __import__()  function?

Boštjan Mejak

unread,
Jul 21, 2015, 5:09:31 PM7/21/15
to wxPython Help
Ah, my code doesn't work at all. Fucking shit! The module that I import via  importer.tryToImport("sys")  doesn't actually import the sys module. What the fuck should I do?!

tjohnson

unread,
Jul 21, 2015, 6:30:57 PM7/21/15
to wxPython-users
__import__(module) cannot be used as a drop-in replacement for import module, because it returns the imported module rather than initializing it as a variable. This link may be helpful: http://effbot.org/zone/import-string.htm

There are several alternatives to using the import statement or the __import__() function:
  1. You can use exec(), which is probably undesirable.
  2. You can use the imp module.
  3. You can use the importlib module (as Werner suggested).
These links may also be helpful:

Boštjan Mejak

unread,
Jul 22, 2015, 6:13:31 AM7/22/15
to wxPython Help
I am trying and trying and I can't actually import the module name given as an argument to my function tryToImport(). The import module does not work, then __import__(module) doesn't work either, neither does module = __import__(module). Also tried importlib.import_module(module) and that also doesn't work. Nothing on this world can't import a module, just the  import  statement.

Boštjan Mejak

unread,
Jul 22, 2015, 6:22:41 AM7/22/15
to wxPython Help
def tryToImport(module):

    try:
        import importlib
        importlib.import_module(module)

    except ImportError:
        print("The import failed.")


Try to create the exact same function, as is above, in your interpreter and then do this:
tryToImport("wx")

You will notice that everything went smoothly, until you do this:
wx

Now what the hell is this? A NameError I get? But I just imported wx with no errors. Well, my friend, that's my hell that I am going through.

tjohnson

unread,
Jul 22, 2015, 7:15:35 AM7/22/15
to wxPython-users
I understand your problem. All of the Python functions that import modules (__import__, importlib.import_module, and imp.load_source) will only return the module as an object. They will NOT add it to the global namespace. Try using this code for your function (obtained from this StackOverflow answer):

def tryToImport(module):
    try:
        globals()[module] = __import__(module)
    except:

        print("The import failed.")

Boštjan Mejak

unread,
Jul 22, 2015, 1:55:59 PM7/22/15
to wxPython Help
Your code doesn't work. Try importing sys using your code in the interactive interpreter and then type sys and hit Enter. You'll get a NameError as if sys wasn't imported at all.

I'm struggling with this for days now.

Tim Roberts

unread,
Jul 22, 2015, 3:59:07 PM7/22/15
to wxpytho...@googlegroups.com
Boštjan Mejak wrote:
Your code doesn't work. Try importing sys using your code in the interactive interpreter and then type sys and hit Enter. You'll get a NameError as if sys wasn't imported at all.

I'm struggling with this for days now.

Days?  Seriously?  Consider this:

    def one():
        x = 3
   
    one()
    print( x )

That fails in exactly the same way for exactly the same reason.  Can you see why?
-- 
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

Cody

unread,
Jul 22, 2015, 4:00:37 PM7/22/15
to wxpytho...@googlegroups.com
Hi,

Not sure why you want to try and conditionally import the sys module. It will always exist never going to fail. Anyway your problem just appears to be a fundamental misunderstanding of between what a variable is and the value that is assigned to the variable..

The import functions return an instance of the module object, this instance not automatically bound to a name in the global namespace like is done when using the normal import keyword statement. 

Also unlike the "import" statement ( import foo) the import function takes a string as an argument not an unbound variable ( import_module("moduleName") vs import moduleName ) the later keyword statement has special hook that calls the import function and then assigns the loaded object to the named variable in the global namespace. 

You, probably would have been able to catch this mistake in your earlier attempts if you had actually looked at the message in the exception that was generated as it would have have said something an failed to import "module" where "module" was literally the name of the module it tried to import and not the _value_ of the string variable you had passed in.


Output from interactive session:
* First note that import_module returns the module as a local variable (I assigned the "sys" module to variable 'x')
* dir shows that it is the contents of the sys module
* Then assign x to "sys" in globals, there will now be a global "sys" variable that references the sys module
* dir(sys) now shows that the global "sys" is the sys module

Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> import importlib
>>> x = importlib.import_module("sys")
>>> dir(x)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__', '__s
tderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_g
etframe', '_mercurial', 'api_version', 'argv', 'builtin_module_names', 'byteorde
r', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_
write_bytecode', 'exc_clear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix
', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckint
erval', 'getdefaultencoding', 'getfilesystemencoding', 'getprofile', 'getrecursi
onlimit', 'getrefcount', 'getsizeof', 'gettrace', 'getwindowsversion', 'hexversi
on', 'long_info', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'pa
th', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'p
y3kwarning', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'settrace',
'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoptio
ns', 'winver']
>>> globals()["sys"] = x
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__package__', '__s
tderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_g
etframe', '_mercurial', 'api_version', 'argv', 'builtin_module_names', 'byteorde
r', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_
write_bytecode', 'exc_clear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix
', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckint
erval', 'getdefaultencoding', 'getfilesystemencoding', 'getprofile', 'getrecursi
onlimit', 'getrefcount', 'getsizeof', 'gettrace', 'getwindowsversion', 'hexversi
on', 'long_info', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'pa
th', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'p
y3kwarning', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'settrace',
'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoptio
ns', 'winver']
>>> print sys.version
2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)]
>>>


Cody

Boštjan Mejak

unread,
Jul 22, 2015, 4:42:45 PM7/22/15
to wxPython Help
There is no god. I just can't make my function to work. I am giving you the file named importer.py in the attachment for you to look at and modify at will. Import the module importer in the ineractive interpreter and do importer.tryToImport("sys") and then after this type in sys and hit Enter. You'll get a NameError.
importer.py

Cody

unread,
Jul 22, 2015, 4:56:23 PM7/22/15
to wxpytho...@googlegroups.com
Hi,

Globals are per module. if your importing an external module but using its local 'globals' the imported module will only exist there.

Modify to pas the globals from the calling context

def tryToImport(module, g):
     m = import_module(module)
     g[module] = m




On Wed, Jul 22, 2015 at 3:42 PM, Boštjan Mejak <bostjan...@gmail.com> wrote:
There is no god. I just can't make my function to work. I am giving you the file named importer.py in the attachment for you to look at and modify at will. Import the module importer in the ineractive interpreter and do importer.tryToImport("sys") and then after this type in sys and hit Enter. You'll get a NameError.

--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-user...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

tjohnson

unread,
Jul 22, 2015, 5:02:05 PM7/22/15
to wxPython-users, bostjan...@gmail.com

I tested my function before posting it. The screenshot shows that it works for me. What version of Python are you using?

Boštjan Mejak

unread,
Jul 22, 2015, 5:32:12 PM7/22/15
to wxPython Help
Cody, running your code I get this:
TypeError: tryToImport() missing 1 required positional argument: 'g'

Can you give me a non-boiler-plate code? I tried to pass  globals()  to the 'g' argument, so my function definition looked like  def tryToImport(module, g=globals())  but that did the same thing – I got that stupid NameError again when I called sys.

Cody

unread,
Jul 22, 2015, 5:41:17 PM7/22/15
to wxpytho...@googlegroups.com
Well when you have a method that takes two parameters you need to pass 2 parameters to it.

Also as mentioned you need to pass the globals() in where you are calling the function and from not the context of where the method is defined. globals() is a method that returns a dict and if you use it as a default parameters the method is evaluated at import time not call time so of course you will get same thing as you are using the same globals from the importer module as you did before when it was in the method.

# your "library" code

def tryToImport(module, g):
    try:
        moduleObject = importlib.import_module(module)
        g[module] = moduleObject
    except ImportError:
        print "Fail"
......

Using it from another place:

import importer

importer.tryToImport("sys", globals())


This will inject the module in the globals of the calling context and not the globals of your 'library'  module. Again must pass the globals() in at the calling location not the declaration.

I am officially out of spoons now ;)


Cody

Boštjan Mejak

unread,
Jul 22, 2015, 6:08:04 PM7/22/15
to wxPython Help
You have officially finished my quest of seeking the answer. Thanks. If anyone runs into the same problem, I am posting my code free to use and modify.
importer.py

Boštjan Mejak

unread,
Jul 22, 2015, 6:28:08 PM7/22/15
to wxPython Help
Fixed the importer module's and the tryToImport() function's docstrings to explain that the module argument must be passed as a string and the namespace argument must be passed with the globals() as a value.
importer.py
Reply all
Reply to author
Forward
Message has been deleted
0 new messages