220

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?

2

8 Answers 8

259

Importing the module doesn't waste anything; the module is always fully imported (into the sys.modules mapping), so whether you use import sys or from sys import argv makes no odds.

The only difference between the two statements is what name is bound; import sys binds the name sys to the module (so sys -> sys.modules['sys']), while from sys import argv binds a different name, argv, pointing straight at the attribute contained inside of the module (so argv -> sys.modules['sys'].argv). The rest of the sys 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 up sys in your global namespace (finds the module), then look up the attribute argv. And yes, by using from sys import argv you can skip the attribute lookup, since you already have a direct reference to the attribute. But the import statement still has to do that work, it looks up the same attribute when importing, and you'll only ever need to use argv once. If you had to use argv thousands of times in a loop, it could perhaps make a difference, but in this specific case it really does not.

Hence, the choice between one or the other should be based solely on coding style.

In a large module, I'd certainly use import sys; code documentation matters, and using sys.argv somewhere in a large module makes it much clearer what you are referring to than just argv ever would.

If the only place you use argv is in a '__main__' block to call a main() function, by all means use from 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)
9
  • 1
    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.)
    – JAB
    Jan 30, 2014 at 16:59
  • 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).
    – neuronet
    Jan 3, 2018 at 17:24
  • 2
    @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. Nov 6, 2018 at 14:50
  • 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 <module>.<function> name
    – Suncatcher
    Apr 16, 2020 at 12:00
  • @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. Apr 16, 2020 at 12:38
59

There are two reasons in favor of using import module rather than from 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 than from module import func.

4
  • 10
    reload() was a builtin in Python 2; that is no longer the case for Python 3.
    – André
    Sep 8, 2017 at 17:38
  • I thought there were also implications to do with circular import dependencies?
    – ADP
    Sep 19, 2019 at 23:55
  • @André importlib.reload is the Python3 way of doing it now: docs.python.org/3/library/importlib.html#importlib.reload Apr 25, 2022 at 17:11
  • @vartec, I was linked to this question because I am doing some programs where specific numpy functions may be used trillions of times, taking days to complete even simple physical simulations. Minimizing the number of calls is not possible without rewriting the entire application in C to begin with. As such minimizing the number of times python has to search the local namespace and the numpy namespace is of top priority.
    – Gerald
    Jan 24 at 18:43
34

I use from imports 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 imports 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
1
  • This is my favorite answer. 'Explicit is better than implicit' sometimes conflicts with readability, simplicity, and DRY. Especially when using a framework like Django.
    – neuronet
    Jan 3, 2018 at 17:27
21

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
1
  • Amen! "import as" is a winning combination :-)
    – paj28
    Mar 4, 2015 at 17:40
4

Although import sys and from sys import agrv both import the entire sys module, the latter uses name binding so only the argv 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 with from sys import argv as sys_argv, a convention that meets the explicit import and is less likely to gave name space collisions.

1
  • 2
    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.
    – msw
    Nov 15, 2015 at 17:54
1

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.

4
  • 1
    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. Jan 8, 2015 at 11:44
  • 2
    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. Jan 8, 2015 at 11:47
  • 1
    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.
    – tmthyjames
    Jan 8, 2015 at 16:07
  • Information is misleading as it lacks the lookup to the module to render usefull results. Apr 25, 2022 at 17:14
-1

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 be datetime

from datetime import datetime, timedelta

so you can say datetime.now() rather than datetime.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.

-2

I just want to add that if you do something like

from math import sin

(or any other built-in library like sys or posix), then sin 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 and io are not built-in packages

Not the answer you're looking for? Browse other questions tagged or ask your own question.