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!"
Related
I have an directory like this
test.py
foo/__init__.py
foo/bar.py
and in the bar.py a simple function:
def say_stuff()
print("Stuff")
And want to call it from the Test.py like this:
import foo
foo.bar.say_stuff()
Then i get the following error:
AttributeError: module 'foo' has no attribute 'bar'
I know to at least fix that error by editing the __init __.py
from .bar import *
But then both of those approaches work:
foo.bar.say_stuff()
foo.say_stuff()
Now my question, how do i get only the foo.bar.say_stuff() to work.
I dont want to load every thing into foo, already beacuse i want clean auto_complete suggestions from my IDE.
Is there any source you can recommend to properly learn pythons import system. All the tutaorals seem too basic and always run into unexpected behavior.
You just need to change from:
from .bar import *
to:
import foo.bar
This behavior is described here:
https://docs.python.org/3/reference/import.html#submodules
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 :)
I keep getting this error: <type 'exceptions.ImportError'> cannot import name get_cert_infos.
I'm pretty sure I'm importing everything correctly. The file with the problem is participant.py and has:
from datetime import date
from widgets import SelectOrAdd, LabelSortedOptionsWidget, DynamicSelect, \
AutocompleteReferenceWidget
from communication import handle_notification, send_email
from utility import create_temp_password, hash_password
from export import get_cert_infos, build_certificate
I have exports.py and the get_cert_infos and build_certificate methods do exist inside of there. I don't understand what the problem is.
I looked at several of the other posts on this and they all seem to be saying that this is most likely a circular import problem
I have export installed and updated export==0.1.2
ImportError: Cannot import name X
Try double checking the spelling, I know it's dumb, but it happens.
if it's not that, try writing this method in export
def hello_world():
print 'hello world'
then
import export
export.hello_world()
if that works, it may be something wrong with the method itself, if it doesn't I imagine that the name export is reserved and is causing conflicts (my code editor doesn't mark it as reserved tho).
is it necessary to import only those two methods? or could you import the whole module and use the needed methods as in the case of the hello_world? does that cause you troubles? if you delete get_cert_infos does build_certificate give you any troubles?
I might be completely wrong here, but I can't find a proper google source for the dilemma that I have:
Let's say we are using python, and we have files
foo.py and bar.py, which have the following pseudocode:
Code in foo.py:
# Code in foo.py
import sys
def foo():
# Some blah code for foo function
And code in bar.py is:
# Code in bar.py
import sys
import foo
def bar():
# Some blah code for bar function
Now, what I am wondering is : Will this not cause code bloat?, since we have imported sys twice in bar.py. Once via import sys and another time because we are doing import foo?
Additionally, what will be the correct thing to do when you have to include libraries in multiple files, which in turn will be included in other files?
Importing a module twice in python does not introduce "bloat". A second import is a mere name-lookup in a cached modules-dictionary (sys.modules, to be precise. Which in case of sys makes this even less relevant, as there is actually nothing that doesn't implicitly trigger an import of sys - although it's obviously not exposed in the namespace).
And what happens if you import some parts of a module x in foo.py, and need them and possibly others in bar.py? Having to carefully groom your imports, and then use foo.something_from_x or x.something_else_from_x in bar.py would be extremely cumbersome to write and maintain.
TLDR: don't worry. Really. Don't.
This would not cause any kind of code bloat . When you import the same library multiple times , python only actually imports it one time (the first time) , and then caches it in sys.modules , and then later on everytime you do import sys , it returns the module object from sys.modules.
A very simple example to show this -
Lets say I have an a.py -
print("In A")
This would print In A everytime the module is imported. Now lets try to import this in multiple times -
>>> import a
In A
>>> import a
>>> import a
>>> import a
As you can see the code was imported only once actually, the rest of the times the cached object was returned. To check sys.modules -
>>> import sys
>>> sys.modules['a']
<module 'a' from '\\path\to\\a.py'>
When you import a module, what happens is that python imports the code , and creates a module object and then creates a name in the local namespace with either the name of the module (if no as keyword was provided , otherwise the name provided after as keyword) , and assigns the module object to it.
The same thing happens when doing it when importing in other modules. Another example -
b.py -
import a
print("In B")
c.py -
import b
import a
print("In C")
Result of running c.py -
In A
In B
In C
As you can see , a.py was only imported once.
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 :)