'import module' vs. 'from module import function'
I have always been using this method:
from sys import argv
and use
argv
with just argv. But there is a convention of using this:import sys
and using the argv by
sys.argv
The second method makes the code self documented and I (really) adhere to it. But the reason I prefer first method is it is fast because we are importing only the function that is needed rather than import the whole module (which contains more useless functions which python will waste time importing them). Note that I need just argv and all other functions from sys are useless to me.
So my questions are. Does the first method really makes the script fast? Which method is preferred most? Why?
Importing the module doesn't waste anything; the module is always fully imported (into the
sys.modules
mapping), so wether you useimport sys
orfrom sys import argv
makes no odds.The only difference between the two statements is what name is bound;
import sys
binds the namesys
to the module (sosys
->sys.modules['sys']
), whilefrom sys import argv
binds a different name,argv
, pointing straight at the attribute contained inside of the module (soargv
->sys.modules['sys'].argv
). The rest of thesys
module is still there, whether you use anything else from the module or not.There is also no performance difference between the two approaches. Yes,
sys.argv
has to look up two things; it has to look upsys
in your global namespace (finds the module), then look up the attributeargv
. And yes, by usingfrom sys import argv
you can skip the attribute lookup, since you already have a direct reference to the attribute. But theimport
statement still has to do that work, it looks up the same attribute when importing, and you'll only ever need to useargv
once. If you had to useargv
thousands of times in a loop it could perhaps make a difference, but in this specific case it really does not.The choice between one or the other then, should be based on coding style instead.
In a large module, I'd certainly use
import sys
; code documentation matters, and usingsys.argv
somewhere in a large module makes it much clearer what you are referring to than justargv
ever would.If the only place you use
argv
is in a'__main__'
block to call amain()
function, by all means usefrom sys import argv
if you feel happier about that:if __name__ == '__main__': from sys import argv main(argv)
I'd still use
import sys
there myself. All things being equal (and they are, exactly, in terms of performance and number of characters used to write it), that is just easier on the eye for me.If you are importing something else altogether, then perhaps performance comes into play. But only if you use a specific name in a module many times over, in a critical loop for example. But then creating a local name (within a function) is going to be faster still:
import somemodule def somefunction(): localname = somemodule.somefunctionorother while test: # huge, critical loop foo = localname(bar)
There is also the situation where you have a package with subpackages or modules that exposes an attribute of one of those subpackages/modules in the top level package. Using `from...import` allows you to do `package.attribute` rather than `package.subpackage_or_module.attribute`, which can be useful if you have logical or conceptual groupings within the package but want to make things a bit more convenient for users of your package. (`numpy` does something like this, I believe.)
In django you have tons of spots where things like `from django.core.management.base import BaseCommand` are better,and anything else (especially `import django`) would lead to unreadable code. So while I like this answer, I think there are some libraries (and especially some frameworks) in which the convention is to violate the bare import. As always, use your judgment about what is best in a given situation. But err on the side of explicit (in other words I agree for the most part).
@JAB: you can still use `import ... as` to find the package to a different name: `import package.subpackage_or_module as shortname`. `from parent import sub` does, essentially, the same thing.
`so wether you use import sys or from sys import argv makes no odds` this seems to be not the case with IDLE. just importing the module does not import its functions and I can call it in IDLE shell only by . name
@Suncatcher: do read my answer in full. The sentence you quote talks about how much is being imported, not what name is bound. That's covered elsewhere in the answer.
There are two reasons in favor of using
import module
rather thanfrom module import function
.First is the namespace. Importing a function into the global namespace risks name collisions.
Second isn't that relevant to standard modules, but significant for you own modules, especially during development. It's the option to
reload()
a module. Consider this:from module import func ... reload(module) # func still points to the old code
On the other hand
import module ... reload(module) # module.func points to the new code
As for speed...
we are importing only the function that is needed rather than import the whole module (which contains more useless functions which python will waste time importing them)
Whether you import a module or import a function from a module, Python will parse the whole module. Either way the module is imported. "Importing a function" is nothing more than binding the function to a name. In fact
import module
is less work for interpreter thanfrom module import func
.reload() was a builtin in Python 2; that is no longer the case for Python 3.
I thought there were also implications to do with circular import dependencies?
I use
from import
s whenever it improves readability. For example, I prefer (semicolons are only to save space here):from collections import defaultdict from foomodule import FooBar, FooBaz from twisted.internet.protocol import Factory defaultdict(); FooBar(); FooBaz(); Factory()
instead of:
import collections import foomodule import twisted.internet.protocol collections.defaultdict(); foomodule.FooBar(); foomodule.FooBaz() twisted.internet.protocol.Factory()
The latter is harder to read (and write) for me because it contains so much redundant information. Also, it's useful to know ahead of time what parts of a module I'm using.
I prefer regular
import
s if I'm using lots of short names from a module:import sys sys.argv; sys.stderr; sys.exit()
Or if a name is so generic that it doesn't make sense outside of its namespace:
import json json.loads(foo) from json import loads loads(foo) # potentially confusing
This is my favorite answer. 'Explicit is better than implicit' sometimes conflicts with readability, simplicity, and DRY. Especially when using a framework like Django.
In my opinion using regular
import
improves readability. When reviewing Python code I like seeing where the given function or class comes from right where it is used. It saves me from scrolling to the top of the module to get that info.As for the long module names I just use the
as
keyword and give them short aliases:import collections as col import foomodule as foo import twisted.internet.protocol as twip my_dict = col.defaultdict() foo.FooBar() twip_fac = twip.Factory()
As an exception I always use the
from module import something
notation when I deal with the__future__
module. You just can't do it another way when you want all strings to be unicode by default in Python 2, e.g.from __future__ import unicode_literals from __future__ import print_function
Amen! "import as" is a winning combination :-)
Although
import sys
andfrom sys import agrv
both import the entiresys
module, the latter uses name binding so only theargv
module is accessible to rest of the code.For some people this would be the preferred style since it only makes accessible the function you explicitly stated.
It does however introduce potential name conflicts. What if you had another module named
argv
? Note you can also explicitly import the function and rename withfrom sys import argv as sys_argv
, a convention that meets the explicit import and is less likely to gave name space collisions.So how is `if sys_argv:` any better than `if sys.argv:`? I know what the second statement means, I have no idea what the first form means without backtracking to the bizarre import.
I recently asked this question to myself. I timed the different methods.
requests library
def r(): import requests return 'hello' timeit r() # output: 1000000 loops, best of 3: 1.55 µs per loop def rg(): from requests import get return 'hello' timeit rg() # output: 100000 loops, best of 3: 2.53 µs per loop
beautifulsoup library
def bs(): import bs4 return 'hello' timeit bs() # output: 1000000 loops, best of 3: 1.53 µs per loop def be(): from bs4 import BeautifulSoup return 'hello' timeit be() # output: 100000 loops, best of 3: 2.59 µs per loop
json library
def js(): import json return 'hello' timeit js() # output: 1000000 loops, best of 3: 1.53 µs per loop def jl(): from json import loads return 'hello' timeit jl() # output: 100000 loops, best of 3: 2.56 µs per loop
sys library
def s(): import sys return 'hello' timeit s() # output: 1000000 loops, best of 3: 1.55 µs per loop def ar(): from sys import argv return 'hello' timeit ar() # output: 100000 loops, best of 3: 2.87 µs per loop
It seems to me that there is a slight difference in performance.
You are adding in an attribute lookup. To compare `import module` with `from module import name` correctly, *add* that name lookup to the `import module` case. E.g. add the line `sys.argv` to the `ar` test, etc. There will still be a difference, because the work done is *slightly* different, as different bytecode is generated and different codepaths are executed.
Note that I directly address that difference in my answer; there will be a difference between using `import sys` then using `sys.argv` thousands of time in a loop vs. `from sys import argv` then using just `argv`. But you don't. For things you do just *once* at the global level of your module, you really should optimise for readability, not microscopic differences in timings.
Ahhhh! And I thought I was on to something! :) I only skimmed your answer. Looks like I jumped the gun on that one. Feels good to be humbled.
Looking at published code fragments, importing entire modules and referring to
module.function
is pretty much the standard, at least for standard modules. The one exception seems to bedatetime
from datetime import datetime, timedelta
so you can say
datetime.now()
rather thandatetime.datetime.now()
.If you are concerned about performance, you can always say (for example)
argv = sys.argv
and then do your performance critical code since the module lookup is already done. However although this will work with functions/methods, most IDE's will get confused and won't (for example) display a source link/signature for the function when it's assigned to a variable.
I just want to add that if you do something like
from math import sin
(or any other built-in library like
sys
orposix
), thensin
will be included in the documentation for your module (ie when you do>>> help(mymodule)
or$ pydoc3 mymodule
. To avoid this, import using:import math from math import sin as _sin
PS: a built-in library is one that is compiled from C code and included with Python.
argparse
,os
andio
are not built-in packages
License under CC-BY-SA with attribution
Content dated before 6/26/2020 9:53 AM
Tobias Kienzler 4 years ago
See also https://stackoverflow.com/q/710551/321973