[Tutor] A required question

Avi Gross avigross at verizon.net
Fri Nov 23 21:29:55 EST 2018


Alan,

I appreciate the feedback. I am guilty of starting with what was meant to be an example that wandered off into something that looks like I am developing an actual set of methods. 

But on the main topic, I wondered if the language or user community had already built some FUNCTIONALITY along these lines.I was thinking, as usual, across languages and environments so let me explain.

The import statement in R is something like:
library("ggplot2")

When it fails, it generates a serious error.

A sister routine is available with a similar call that instead returns True/False. It happens to be called:

require("ggplot2")

Since it return a TRUE/FALSE value (R uses full uppercase for the pythonic True/False) you can write a function that tests to see if the package was loaded and if not, tries to install it and load it.

if (! require(GARBARGE)) {
  install.packages("GARBARGE")
  library(GARBARGE)
}

Of course since there is no such package, I still get an error. But if it was something that the user on that machine had not loaded but needed, it might pause and lock and load and be able to continue.

BTW, R sometimes requires strings to be quoted but sometimes because of very lazy evaluation, you can skip the quotes and the function can take the naked value off the argument stack before it is evaluated, turn it into a quoted string, and off you go. The install.packages command does not do this but the other two do.

Back to Python. I know how to check if a module is already loaded into a program. But I am not aware of how you can check if it can be loaded except by trying to load it. That may be enough.

<<CODE>>

print("-=" * 20)
print("Trying to import non-existent module garbarge")
try:
    import garbarge
except:
    print("failed")
else:
    print("I am drowning in garbarge!!!")

print("=-" * 20)
print("Getting ready to process numbers with module numpy.")
try:
    import numpy
except:
    print("drat! failed again")
else:
    print("I can calculate on numpy!")

print("-=" * 20)

<<OUTPUT>>
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Trying to import non-existent module garbarge
failed
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Getting ready to process numbers with module numpy.
I can calculate on numpy!
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

<<BACK FOR FINAL COMMENT>>
In that code, I suppose, you could insert an appropriate call to load the failed module and try again. I could design and write a function like that BUT I am going to behave 😉

Hope that helps explain where I am coming from. Since I can see how to write such tools, I have to suspect it has been done, not just once, but a seemingly infinite number of times.

And note actually importing a module to test if it can be can have side effects.
So, to add value, I am going to partially answer my own question. There are modules that help.


import imp
>>> imp.find_module('eggs')
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    imp.find_module('eggs')
  File "C:\Users\avid2016\AppData\Local\Programs\Python\Python37-32\lib\imp.py", line 297, in find_module
    raise ImportError(_ERR_MSG.format(name), name=name)
ImportError: No module named 'eggs'

>>> imp.find_module('pandas')
(None, 'C:\\Users\\avid2016\\AppData\\Roaming\\Python\\Python37\\site-packages\\pandas', ('', '', 5))

So I took a quick try to see if I could slightly replicate an attempt to load. No guarantees this exact code works anywhere else:

I hardc-oded in "pandas" as the first try:

modulosity = "pandas"

print(" importing " + modulosity + "By hook or by crook.")

import imp
var = imp.find_module(modulosity)

if var:
    print ("FOUND: " + modulosity + " at " + str(var))
else:
    print("Module needs loading:" + modulosity)
    import os
    os.system("python -m pip install " + modulosity)

exec(f"import {modulosity}")

Output:

importing pandasBy hook or by crook.

Warning (from warnings module):
  File "C:/Users/avid2016/AppData/Local/Programs/Python/Python37-32/temp.py", line 28
    import imp
DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
FOUND: pandas at (None, 'C:\\Users\\avid2016\\AppData\\Roaming\\Python\\Python37\\site-packages\\pandas', ('', '', 5))

Now replacing pandas by non-existent koala:

importing koalaBy hook or by crook.

Warning (from warnings module):
  File "C:/Users/avid2016/AppData/Local/Programs/Python/Python37-32/temp.py", line 28
    import imp
DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
Traceback (most recent call last):
  File "C:/Users/avid2016/AppData/Local/Programs/Python/Python37-32/temp.py", line 29, in <module>
    var = imp.find_module(modulosity)
  File "C:\Users\avid2016\AppData\Local\Programs\Python\Python37-32\lib\imp.py", line 297, in find_module
    raise ImportError(_ERR_MSG.format(name), name=name)
ImportError: No module named 'koala'

Amazingly it failed!

Calling it a night as I find errors even after I rewrite it like this;

modulosity = "SimPy"

print(" importing " + modulosity + "By hook or by crook.")

import imp
try:
    var = imp.find_module(modulosity)
    print ("FOUND: " + modulosity + " at " + str(var))
except:
    print("NOT FOUND")
    print("Module needs loading: " + modulosity)
    import os
    os.system("python -m pip install " + modulosity)
    
exec(f"import {modulosity}")

I am sure something is doable and can be made into a proper function. Yes, I cheated by using exec. But it is now after Spanksgiving.

-----Original Message-----
From: Tutor <tutor-bounces+avigross=verizon.net at python.org> On Behalf Of Alan Gauld via Tutor
Sent: Friday, November 23, 2018 10:35 AM
To: tutor at python.org
Subject: Re: [Tutor] A required question

On 23/11/2018 05:34, Avi Gross wrote:
> Just to be different, and perhaps return to the purpose of this group,

Actually I think the higher level debate of Python's direction as a teaching language is entirely appropriate for this group. It kind of defines the group and and its current and future role.

Whereas...

> What I was thinking was the ability to do something like this:
> 
> import ReChoir as require
> 
> require.version(condition, before=True, after=False) 
> require.modules(module list, recursive=True) require.os([“Eunuchs”, 
> “Windblows”])
> require.functionality(“print3”)

I can see the logic but suspect discussion of new features is probably the preserve of the main Python list. If you can get traction there somebody might actually go ahead and write one!

On the tutor list such matters are usually adequately covered by virtual environments etc.

--
Alan G




More information about the Tutor mailing list