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 :)
Related
One of the ways I recently started structuring my programming is by having one main file and multiple different appropriately named files that represent different parts of the project that I am working on.
All different Python Files in one folder.
To then use one file I would simply type:
import filename
This works all well and good, but I noticed that I can't use variables from within another file in that code.
My question is can I import variables, or pass variables from one file to another to make use of them later again?
Each file you import is considered to have its own namespace. You can reference anything in that namespace if you prefix it with the module name.
For example, f you have a file like this:
# filename.py
foobar = 42
You can access foobar with filename.foobar. For example:
import filename
print("foobar is %s" % filename.foobar)
Another way is to use __builtin__ module so that your file main_file.py will contain:
print(thing)
while your whatever.py will contain:
import __builtin__
__builtin__.thing = 1
import main_file
More on that: here
Not sure this is possible, but would like to know if there are any suggestions.
Say I have a file foo.py which looks like
import doesnotexist
bar = "Hello, World!"
I want to do a from foo import bar, but this will fail due to the import not existing in the scope of this new file.
One way of doing this is putting bar in a new file called bar.py and have foo.py also import that, but would like to skip that if possible.
Any ideas?
There is no way to import only part of a module - Python will load the entire module before pulling the parts you asked for.
As mentioned in the comments, you can capture the import error inside the module and ignore it. Your code will then generate an error if you try to use the module that didn't import.
try:
import doesnotexist
except ImportError:
pass
bar = "Hello, World!"
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 :)
Suppose I have a module foo.py and a package foo/. If I call
import foo
which one will be loaded? How can I specify I want to load the module, or the package?
I believe the package will always get loaded. You can't work around this, as far as I know. So change either the package or the module name. Docs: http://docs.python.org/tutorial/modules.html#the-module-search-path
Actually, it is possible, by manually guiding the import machinery to use a .py file instead of directory. (This code is not well tested, but seems to work). UPDATE 2020: Note that this requires using custom import_module() function instead of normal import statement. However, with modern Python3 and its importlib, it might be possible to make the bare import statement to work the same way too. (Note that this answer shows flexibility which Python offers. It's not an encouragement to use this in your applications. Use this only if you know what you're doing.)
File foo.py
print "foo module loaded"
File foo/__init__.py
print "foo package loaded"
File test1.py
import foo
File test2.py
import os, imp
def import_module(dir, name):
""" load a module (not a package) with a given name
from the specified directory
"""
for description in imp.get_suffixes():
(suffix, mode, type) = description
if not suffix.startswith('.py'): continue
abs_path = os.path.join(dir, name + suffix)
if not os.path.exists(abs_path): continue
fh = open(abs_path)
return imp.load_module(name, fh, abs_path, (description))
import_module('.', 'foo')
Running
$ python test1.py
foo package loaded
$ python test2.py
foo module loaded
Maybe you want to move your classes from foo.py module to __init__.py.
This way you'll be able to import them from the package as well as importing optional subpackages:
File foo/__init__.py:
class Bar(object):
...
File foo/subfoo.py:
class SubBar(object):
...
File mymodule.py:
from foo import Bar
from foo.subfoo import SubBar
In interactive python I'd like to import a module that is in, say,
C:\Modules\Module1\module.py
What I've been able to do is to create an empty
C:\Modules\Module1\__init__.py
and then do:
>>> import sys
>>> sys.path.append(r'C:\Modules\Module1')
>>> import module
And that works, but I'm having to append to sys.path, and if there was another file called module.py that is in the sys.path as well, how to unambiguously resolve to the one that I really want to import?
Is there another way to import that doesn't involve appending to sys.path?
EDIT: Here's something I'd forgotten about: Is this correct way to import python scripts residing in arbitrary folders? I'll leave the rest of my answer here for reference.
There is, but you'd basically wind up writing your own importer which manually creates a new module object and uses execfile to run the module's code in that object's "namespace". If you want to do that, take a look at the mod_python importer for an example.
For a simpler solution, you could just add the directory of the file you want to import to the beginning of sys.path, not the end, like so:
>>> import sys
>>> sys.path.insert(0, r'C:\Modules\Module1')
>>> import module
You shouldn't need to create the __init__.py file, not unless you're importing from within a package (so, if you were doing import package.module then you'd need __init__.py).
inserting in sys.path (at the very first place) works better:
>>> import sys
>>> sys.path.insert(0, 'C:/Modules/Module1')
>>> import module
>>> del sys.path[0] # if you don't want that directory in the path
append to a list puts the item in the last place, so it's quite possible that other previous entries in the path take precedence; putting the directory in the first place is therefore a sounder approach.