3

Sorry if this is a very novice question, I was just wondering one thing.

When in python and your code is split up amongst multiple files, how would you avoid a ton of imports on the same thing?

Say I have 2 files. Main, and Content.

Main:

import pygame
from pygame.locals import *
pygame.display.init()
blah

Content:

import pygame
from pygame.locals import *
pygame.display.init()
load content and stuff

pygame is imported twice and display.init is called twice. This is problematic in other places. Is there anyway to get around this, or must it just import and import and import?

One situation I can think of is this: A script that writes to a file everytime it is imported. That way, if it's imported 3 times, it gets run 3 times, therefore writing to the file 3 times.

Thanks in advance!

dbr
  • 153,498
  • 65
  • 266
  • 333
SuperDisk
  • 109
  • 8

3 Answers3

6

You misunderstand what import does. It's not the same as include. Loaded modules are singletons and their corresponding files are not evaluated twice.

That said, a well-constructed module will not have side-effects on import. That's the purpose of the if __name__=='__main__' idiom.

Do not attempt to "clean up" your imports. Import everything you need to use from within a file. You could make less use of import *, but this is purely for code readability and maintainability.

Francis Avila
  • 29,546
  • 6
  • 54
  • 93
  • Right (see also [earlier similar question](http://stackoverflow.com/questions/2029523/how-to-prevent-a-module-from-being-imported-twice)), although there are odd corner cases where you can fool Python into thinking that two modules are different when they are actually the same; see [koichitamura blog entry](http://koichitamura.blogspot.com/2009/07/ill-show-you-case-where-one-file.html). – torek Mar 09 '12 at 01:29
  • 1
    @francis The advice for less use of "import * " is important - however, the "pygame.locals" module is a special case which is designed to work like this - it just contains numeric constants bound to upper case variables, like key codes, video modes, and so on. – jsbueno Mar 09 '12 at 04:02
3

You should avoid having anything happen at import(except, see further down). a python file is a module first, so it can and should be used by other python modules. If something "happens" in the import stage of a python file, then it may happen in an undesirable way when that file is imported by another module.

Each module should just define things to be used: classes, functions, constants, and just wait for something else to use them.


Obviously, if no script ever does at import, then it's not possible for anything to actually get used and make stuff "happen". There is a special idiom for the unusual case that a module was called directly. Each python file has a variable, __name__ automatically created with the module name it was imported as. When you run a script from the command line (or however you have started it), it wasn't imported, and there's no name for it to have, and so the __name__ variable will have a special value "__main__" that indicates that it's the script being executed. You can check for this condition and act accordingly:

# main.py
import pygame
from pygame.locals import *

import content

def init():
    pygame.display.init()

def stuff():
    content.morestuff()

if __name__ == '__main__':
    init()
    stuff()
# content.py
import pygame
from pygame.locals import *

def init():
    pygame.display.init()

def morestuff():
    "do some more stuff"

if __name__ == '__main__':
    init()
    morestuff()

This way; init() and thus pygame.display.init() are only ever called once, by the script that was run by the user. the code that runs assuming that init() has already been called is broken into another function, and called as needed by the main script (whatever that happens to be)

SingleNegationElimination
  • 137,315
  • 28
  • 247
  • 284
0

import statements are supposed to be declarations that you're using something from another module. They shouldn't be used to cause something to happen (like writing to a file). As noted by Francis Avila, Python will try not to execute the code of a module more than once anyway.

This has the consequence that whether a given import statement will cause anything to happen is a global property of the application at runtime; you can't tell just from the import statement and the source code of the module, because it depends on whether any other code anywhere else in the project has already imported that module.

So having a module "do something" when executed is generally a very fragile way to implement your application. There is no hard and fast definition of "do something" though, because obviously the module needs to create all the things that other modules will import from it, and that may involve reading config files, possibly even writing log files, or any number of other things. But anything that seems like the "action" of your program, rather than just "setting up" things to be imported from the module, should usually not be done in module scope.

Ben
  • 56,956
  • 19
  • 113
  • 151