81

I'm currently writing a class that needs os, stat and some others.

What's the best way to import these modules in my class?

I'm thinking about when others will use it, I want the 'dependency' modules to be already imported when the class is instantiated.

Now I'm importing them in my methods, but maybe there's a better solution.

Paul
  • 20,883
  • 7
  • 57
  • 74

4 Answers4

53

If your module will always import another module, always put it at the top as PEP 8 and the other answers indicate. Also, as @delnan mentions in a comment, sys, os, etc. are being used anyway, so it doesn't hurt to import them globally.

However, there is nothing wrong with conditional imports, if you really only need a module under certain runtime conditions.

If you only want to import them if the class is defined, like if the class is in an conditional block or another class or method, you can do something like this:

condition = True

if condition:
    class C(object):
        os = __import__('os')
        def __init__(self):
            print self.os.listdir

    C.os
    c = C()

If you only want it to be imported if the class is instantiated, do it in __new__ or __init__.

agf
  • 171,228
  • 44
  • 289
  • 238
  • 16
    If I import a module in a method (such as `__init__`), wouldn't it import that module multiple times if I create multiple instances? Therefore, would it affect the performance, compared to importing it globally? – Markus Meskanen Jun 11 '14 at 11:00
  • 1
    Shouldn't it () after the __import, not []? I get the error "TypeError: 'builtin_function_or_method' object has no attribute '__getitem__'" when I use brackets. After I change it to () it works, but I have to prefix the imported module with the class's name, even when using the imported module inside the class, I would rather not do that. Any way around this? – Samuel Nov 18 '14 at 17:51
  • 2
    @Samuel: Thanks for the correction, I fixed the import. If you want the imported object to be available globally, just use the normal `import` statement. That's not really a good idea with conditional imports though, as you can then have code *outside* the conditional that only works if the branch of the conditional with the import has executed first. If you use `__import__` as above, you avoid creating a global name for the object. – agf Nov 18 '14 at 17:56
  • 1
    I see. I want a global name, but I want a conditional import. I'm importing the xlsxwriter module based on the output format the user chooses, so I don't always want to import it. Thanks for your help! This tells me what is possible and how to do it. – Samuel Nov 18 '14 at 18:32
  • how can I apply `__import__` for from imports – alper May 20 '22 at 10:18
  • @alper [See the example in the docs](https://docs.python.org/3/library/functions.html#import__): `_temp = __import__('spam.ham', globals(), locals(), ['eggs', 'sausage'], 0)` then `eggs, saus = _temp.eggs, _temp.sausage` – agf May 20 '22 at 17:52
19
import sys
from importlib import import_module

class Foo():

    def __init__(self):

       # Depends on the configuration of the application.
        self.condition = True # "True" Or "False"

        if self.condition:
            self.importedModule = import_module('moduleName')

        # ---
        if 'moduleName' in sys.modules:
            self.importedModule.callFunction(params)

        #or

        if self.condition:
            self.importedModule.callFunction(params)
        # ---
nvd
  • 2,995
  • 28
  • 16
  • Why do we need `self.condition`? – alper Jul 25 '22 at 15:28
  • @alper The value of the condition, "self.condition", decides if a specific module is needed or not. It may come from the settings that the application reads at startup. – nvd Jul 25 '22 at 19:23
  • can I add the module I imported in class to global scope somehow? so I could see it in dir() ? – aleXela Dec 18 '22 at 15:50
  • @aleXela You may try declaring it before "def init" as class global as "importedModule = None" and later update it. – nvd Dec 20 '22 at 21:18
  • can u point me to some doc how to make it? – aleXela Dec 23 '22 at 15:36
16

PEP 8 on imports:

Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants.

This makes it easy to see all modules used by the file at hand, and avoids having to replicate the import in several places when a module is used in more than one place. Everything else (e.g. function-/method-level imports) should be an absolute exception and needs to be justified well.

  • 22
    This is for __unconditional imports__. If you only want to import them if that class is instantiated, obviously this doesn't apply. – agf Jul 28 '11 at 15:31
  • @agf: There's very rarely a reason to import conditionally though. Especially with the modules OP uses, those are probably already in use by the implementation (try `python -c "import sys; print sys.modules.keys()"`). –  Jul 28 '11 at 15:32
1

This (search for the section "Imports") official paper states, that imports should normally be put in the top of your source file. I would abide to this rule, apart from special cases.

Tomer Cohen
  • 374
  • 6
  • 13
Constantinius
  • 34,183
  • 8
  • 77
  • 85
  • 1
    Here's one special case. You want to fail gracefully if a user doesn't have a particular library installed. Suppose you have a script that does a bunch of stuff, and optionally it pushes logs to a log server. The library for the log server might not be installed. If that is the case you want the script to still run. If the user configured logging, we can print the error then and exit. But if the user didn't configure logging, the script should still be able to run without logging. Putting the import at the top of the script means it will fail all the time if the library is not installed. – fdmillion Aug 09 '21 at 21:12