I am wanting to call different imports based on the value of a variable in python.
Normally I may do this with a switch statement, but alas python has none...
I was thinking about having a list of functions each of which contains a different import, but is there a better way? Is it possible to list imports in a similar way to methods? Or store the module names as strings in a list, then convert them into a form that can be used to import them?
Thanks
If you want to import a module programatically, you can do
module = __import__('module_name')
It seems like a strange situation to find yourself in though.. check your design and proceed with care.
Usually, in Python, you can replace a switch structure by a dictionary. To import a module using a name stored into a string, you can use importlib.import_module(). Here is an example:
from importlib import import_module
modlist = {'case 1': ('package1', 'module1'), 'case 2': ('package2', 'module2')}
myvar = 'case 2'
mypackage, mymodule = modlist[myvar]
import_module(mymodule, mypackage)
Why don't you use if?
if a is "import_module1":
import module1
elif a is "import_module2":
import module2
An example from my own code http://felicitous-desktop.googlecode.com/files/felicitous.py
The script sets a desktop background. Depending whether the desktop is Windows or Gnome, it imports different libraries:
if ( platform.system() == "Windows" ):
set_windows_background(dest)
else:
set_gnome_background(dest)
where
def set_gnome_background(x):
import gconf
client = gconf.client_get_default()
client.set_string ("/desktop/gnome/background/picture_filename",x)
def set_windows_background(x):
import ctypes
SPI_SETDESKWALLPAPER = 20 # According to http://support.microsoft.com/default.aspx?scid=97142
import tempfile
from PIL import Image
image = Image.open(x)
bmppath= os.path.normpath(os.path.expanduser("~/epic.bmp"))
image.save (bmppath, "BMP")
print bmppath
ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, bmppath , 0)
Related
Based on some answers I try to be more specific.
I want to import the print and the models AND code in my main.py
I know the question gets asked a lot, but still I could not figure out whats wrong with my code!
I have a project directory like this
-project
--__init__py
--main.py
--print.py
--requests
--__init__.py
--models.py
--code.py
i want to import from print.py and * from requests
Therefore I tried to add these lines in main.py
from . import print
#or
import print
#for requests I tried
import os.path
import sys
sys.path.append('./requests')
from requests import *
all of those lines cause the same ImportError attempted relative import with no known parent ,
using Python 39
anyone an idea where the problem is?
I am very confused that this seems not to work, was it possible in older versions?
You should definitely not be doing anything with sys.path. If you are using a correct Python package structure, the import system should handle everything like this.
From the directory structure you described, project would be the name of your package. So when using your package in some external code you would do
import package
or to use a submodule/subpackage
import project.print
import project.requests
and so on.
For modules inside the package you can use relative imports. When you write
i want to import from print.py and * from requests Therefore I tried
it's not clear from where you want to import them, because this is important for relative imports.
For example, in project/main.py to import the print module you could use:
from . import print
But if it's from project/requests/code.py you would use
from .. import print
As an aside, "print" is probably not a good name for a module, since if you import the print module it will shadow the print() built-in function.
Your main file should be outside the 'project'-directory to use that as a package.
Then, from your main file, you can import using from project.print import ....
Within the project-package, relative imports are possible.
I want to write a Python module that automatically imports all the good stuff for me (about 50 other modules) so I don't have to copy and past them every time I start a new script. I attempted this by defining the following method in my module, soon to realize when I import my module and call this method, the imports take place locally.
def auto_import():
import os
import sys
# plus 50 other modules...
How can I accomplish this automation using modular programming? (I am using Python 3.6. on Ubuntu.)
You don't need a function to do that, you can simply make a file like commonimports.py which looks like this:
import os
import numpy as np
import sys
#and so on...
And add this import statement in other files
from commonimports import *
And you'll have all the modules ready to use within that namespace
Just make the name of your imported modules global:
def auto_import():
import os
import sys
global os, sys
This is not necessary to use this method if you def auto_import() then every time you have to use a autoimport function whenever you want to use those module.
I have written a script for XBMC which optionally downloads a dll and then imports a module that depends on that dll if the download was successful.
However, placing the import inside a function generates a Python syntax warning.
Simplified example:
1 def importIfPresent():
2 if chkFunction() is True:
3 from myOptionModule import *
Line 3 generates the warning, but doesn't stop the script. I can't place this code at the start outside of a function because I need to generate dialog boxes to prompt the download and then hash the file once it is downloaded to check success. I also call this same code at startup in order to check if the user has already downloaded the dll.
Is there a different/better way to do this without generating the syntax warning? Or should I just ignore the warning and leave it as is?
Thank you! Using the useful responses below, I now have:
import importlib
myOptionalModule = None
def importIfPresent():
if chkFunction is True:
try:
myOptionalModule = importlib.import_module('modulex')
except ImportError:
myOptionalModule = None
...
importIfPresent()
...
def laterFunction():
if myOptionalModule != None:
myParam = 'something expected'
myClass = getattr(myOptionalModule, 'importClassName')
myFunction = getattr(myClass, 'functionName')
result = myFunction(myClass(), myParam)
else:
callAlternativeMethod()
I am posting this back mainly to share with other beginners like myself the way I learned through the discussion to use the functionality of a module imported this way instead of the standard import statement. I'm sure that there are more elegant ways of doing this that the experts will share as well...
You're not getting the warning for doing an import inside a function, you're getting the warning for using from <module> import * inside a function. Doing a In Python3, this actually becomes a SyntaxError, not a SyntaxWarning. See this answer for why wildcard imports like this in general, and expecially inside functions are discouraged.
Also, this code isn't doing what you think it does. When you do an import inside a function, the import only takes affect inside the function. You're not importing that module into the global namespace of the file, which I believe is what you're really trying to do.
As suggested in another answer importlib can help you here:
try:
import myOptionModule as opt
except ImportError:
opt = None
def importIfPresent():
global opt
if chkFunction() is True:
opt = importlib.import_module("myOptionModule")
I beleive you need to use the importlib library to facilitate this.
The code would be at the top of the mod:
import importlib
then replace "from myOptionModule import *" with "module = importlib.import_module(myOptionModule)". You can then import the defs/classes you want or import them all by using getattr(module,NAME(S)TOIMPORT).
See if that works.
Check out chapter 30 and 31 of Learning Python by Lutz for more info.
Do I have to take out all the spaces in the file name to import it, or is there some way of telling import that there are spaces?
You should take the spaces out of the filename. Because the filename is used as the identifier for imported modules (i.e. foo.py will be imported as foo) and Python identifiers can't have spaces, this isn't supported by the import statement.
If you really need to do this for some reason, you can use the __import__ function:
foo_bar = __import__("foo bar")
This will import foo bar.py as foo_bar. This behaves a little bit different than the import statement and you should avoid it.
If you want to do something like from foo_bar import * (but with a space instead of an underscore), you can use execfile (docs here):
execfile("foo bar.py")
though it's better practice to avoid spaces in source file names.
You can also use importlib.import_module function, which is a wrapper around __import__.
foo_bar_mod = importlib.import_module("foo bar")
or
foo_bar_mod = importlib.import_module("path.to.foo bar")
More info: https://docs.python.org/3/library/importlib.html
Just to add to Banks' answer, if you are importing another file that you haven't saved in one of the directories Python checks for importing directories, you need to add the directory to your path with
import sys
sys.path.append("absolute/filepath/of/parent/directory/of/foo/bar")
before calling
foo_bar = __import__("foo bar")
or
foo_bar = importlib.import_module("foo bar")
This is something you don't have to do if you were importing it with import <module>, where Python will check the current directory for the module. If you are importing a module from the same directory, for example, use
import os,sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
foo_bar = __import__('foo_bar')
Hope this saves someone else trying to import their own weirdly named file or a Python file they downloaded manually some time :)
If you have a collection of methods in a file, is there a way to include those files in another file, but call them without any prefix (i.e. file prefix)?
So if I have:
[Math.py]
def Calculate ( num )
How do I call it like this:
[Tool.py]
using Math.py
for i in range ( 5 ) :
Calculate ( i )
You will need to import the other file as a module like this:
import Math
If you don't want to prefix your Calculate function with the module name then do this:
from Math import Calculate
If you want to import all members of a module then do this:
from Math import *
Edit: Here is a good chapter from Dive Into Python that goes a bit more in depth on this topic.
Just write the "include" command :
import os
def include(filename):
if os.path.exists(filename):
execfile(filename)
include('myfile.py')
#Deleet :
#bfieck remark is correct, for python 2 and 3 compatibility, you need either :
Python 2 and 3: alternative 1
from past.builtins import execfile
execfile('myfile.py')
Python 2 and 3: alternative 2
exec(compile(open('myfile.py').read()))
If you use:
import Math
then that will allow you to use Math's functions, but you must do Math.Calculate, so that is obviously what you don't want.
If you want to import a module's functions without having to prefix them, you must explicitly name them, like:
from Math import Calculate, Add, Subtract
Now, you can reference Calculate, Add, and Subtract just by their names. If you wanted to import ALL functions from Math, do:
from Math import *
However, you should be very careful when doing this with modules whose contents you are unsure of. If you import two modules who contain definitions for the same function name, one function will overwrite the other, with you none the wiser.
I've found the python inspect module to be very useful
For example with teststuff.py
import inspect
def dostuff():
return __name__
DOSTUFF_SOURCE = inspect.getsource(dostuff)
if __name__ == "__main__":
dostuff()
And from the another script or the python console
import teststuff
exec(DOSTUFF_SOURCE)
dostuff()
And now dostuff should be in the local scope and dostuff() will return the console or scripts _name_ whereas executing test.dostuff() will return the python modules name.
It's easy and simple:
you can just do this:
def run_file(path):
return exec(open(path).read());
run_file("myfile.py");
I would like to emphasize an answer that was in the comments that is working well for me. As mikey has said, this will work if you want to have variables in the included file in scope in the caller of 'include', just insert it as normal python. It works like an include statement in PHP. Works in Python 3.8.5.
Alternative #1
import textwrap
from pathlib import Path
exec(textwrap.dedent(Path('myfile.py').read_text()))
Alternative #2
with open('myfile.py') as f: exec(f.read())
I prefer Alternative #2 and have been using it in my website development.