0

I was wondering if the position of import statements in a python program has any affect on performance. For example if I have this

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import urllib2
import json
import requests
from flask import render_template, request, Flask, session, Markup, jsonify, send_from_directory
from wit import Wit
from os import urandom
from datetime import datetime
from uuid import uuid1
from random import choice
from FAAWrapper import FAA_API
from bs4 import BeautifulSoup



def function1():
    from OpenSSL import SSL
    from fuzzywuzzy import process
    continue

def function2():
    continue

Would performance be adversely affected by calling function1() being that function1 contains import statements? Should all of my imports be placed at the top or does the import only happen once the first time the function is called?

user3282276
  • 3,674
  • 8
  • 32
  • 48
  • for readability its best to put all imports at the top, but if you have a function that needs an import, and that function may not be called, it wouldn't hurt to put it in function – joel goldstick Sep 10 '16 at 22:33
  • You have no `function1` in your sample code. – Martijn Pieters Sep 10 '16 at 22:34
  • @PadraicCunningham Regardless of if it will be a bottleneck I still would like to know – user3282276 Sep 10 '16 at 22:35
  • This can provide an answer: https://docs.python.org/3/library/timeit.html -- This can provide an explaination: https://docs.python.org/3/reference/import.html#the-module-cache – Andrea Corbellini Sep 10 '16 at 22:37
  • http://stackoverflow.com/questions/477096/python-import-coding-style/4789963#4789963 http://stackoverflow.com/questions/128478/should-python-import-statements-always-be-at-the-top-of-a-module they answer your question – Padraic Cunningham Sep 10 '16 at 22:37
  • Doesn't matter, the `continue` in the function causes a syntax error so this will never run anyway. – Stefan Pochmann Sep 10 '16 at 22:37

1 Answers1

6

Importing does two things:

  1. If there is no sys.modules entry yet, find and load the module; if Python code, executing the top-level code produces the namespace for that module. This step is skipped if the module has already been loaded.

  2. Bind a name in the current namespace to the imported object. import foo sets the name foo. from foo import bar binds the name bar, etc.

Now, local names (in functions) have a speed advantage in that Python stores these in a C array and uses indices in the bytecode to reference them. Global names are stored in a dictionary and have a small hashing overhead each time you do a lookup.

So importing something into a function results in a local, accessing which is faster than referencing a global. This is offset by the hash lookup in sys.modules each time your function runs so only if the name is used in a loop would you notice this.

However, you should only make such optimisations if that code is used on a critical path, in code that is executed a lot. You are paying a maintenance price by hiding imports in functions, and that cost needs to be weighed against the (marginal) speed benefits.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343