pythonic way to do checks before imports - python

I have to develop python code for an inhouse framework which can either run in the system's standard python environment or sometimes requires a custom environment to be active. For example, to be able to load certain modules.
Because an ImportError might not be too obvious for any user, I would like to give the user a proper error message, explaining the issue.
Some sample code might look like this:
# standard imports...
import sys
import numpy as np
# import which requires special environment
import myspecialmodule
# [...]
One method would be to check for ImportErrors like this:
# standard imports...
import sys
import numpy as np
# import which requires special environment
try:
import myspecialmodule
except ImportError:
print('not in the env', file=sys.stderr)
sys.exit(1)
# [...]
However, that is quite tedious to do, especially if there are many such scripts or if there are many imports. The question is then, which import has failed, if you do not want to repeat the try/except several times.
Now, I wrote a function guard() which checks for the existence of the environment in another way:
import sys
import os
def guard():
# assume the environment sets this special variable
if 'MYSPECIALENV' in os.environ:
# do more checks if the environment is correctly loaded
# if it is, simply:
return
print("The environment is not loaded correctly. "
"Run this script only in the special environment", file=sys.stderr)
sys.exit(1)
I altered the imports on the script:
# standard imports...
import sys
import numpy as np
# import which requires special environment
guard()
import myspecialmodule
# [...]
The advantage over the try/except method is, that an ImportError is still raised even if the environment is loaded.
But the issue is, that code linters like isort do not like function calls before imports.
Now, one could add configuration to isort to skip this section...
Furthermore, for a reader of the code, it might not be too obvious what is going on.
Of course, I could add some comments explaining it...
Another method I thought of is to write a module which does the job of guard, i.e.:
# file: guard/__init__.py
import sys
import os
if 'MYSPECIALENV' not in os.environ:
print("The environment is not loaded correctly. "
"Run this script only in the special environment", file=sys.stderr)
sys.exit(1)
# standard imports...
import sys
import numpy as np
# import which requires special environment
import guard
import myspecialmodule
# [...]
but this might be even less obvious, especially as imports might be sorted in a different way (again thinking about isort).
Is there a better, more pythonic way to do such things before importing a module? Especially one that is obvious for a future developer as well.

Related

Import pprint by default as a debugging tool

I use pprint.pprint for every debug output I ever make, across every python file I've written is the line from pprint import pprint.
Often times once I have a stable version of that file I forget to drop the import even if all pprint statements are removed.
I would like to have pprint available in all context, all-ways on my development machine so my testing machine will fail when debug output has been left in and so I don't have to spend an alarmingly large portion of my life typing that one line.
How do I pre-import this tool system wide?
As per this answer to a similar question, you could modify /lib/site.py for every different version of Python you have on the system. Note that I highly recommend that you DON'T do this, but if necessary then you could. You should modify it in this way:
import sys
import os
import builtins
import _sitebuiltins
import pprint # <---------------------------- added
...
def main()
"""Add standard site-specific directories to the module search path.
This function is called automatically when this module is imported,
unless the python interpreter was started with the -S flag.
"""
global ENABLE_USER_SITE
builtins.pprint = pprint.pprint # <------ added
...
Beware that this can cause some really funky bugs with production code that uses pprint even though it's never been imported.

when importing functions from inside builtins like os or sys is it good practice to import as protected?

in myModule.py I am importing environ from os , like
from os import environ since I am only using environ, but when I do dir(myModule) it shows environ as publicly visible , how ever should it be imported as protected assuming some other project may also have its own environ function ?
If you're doing from os import environ, then you'll reference it as environ.
If you do import os, it's os.environ.
So depending on your needs, the second option might be better. The first will look better and read easier, whereas the second avoids namespace pollution.
Expanding on #mgilson's comment - when you do dir(somemodule), everything you see is namespaced to that module. In other words, you have to use the . (name resolution operator) to "reach" those items.
So, in myModule.py you have the following lines:
from os import environ
a = 4
In some other module, or the Python prompt, you have the following statements:
import myModule
dir(myModule)
Now, in order to get to a or environ that is inside myModule, you'd have to explicitly define its scope:
print(a) # this won't work
print(myModule.a) # this will print 4
In Python as a general rule, there is no explicit hiding/protecting. Python expects its users to be consenting adults and "know what they are doing".
However, developers can control what happens when someone tries to import everything from a module (from myModule import *), but this isn't strictly enforced. You can still get to everything inside myModule by prefixing the module name.

Initialization of Python program

I have a Python program that stars with a bunch of code where I basically import some modules, initialize some variables and calls a few functions. Here's part of it:
import numpy as np
import scipy as sp
import scipy.optimize as opt
import scipy.constants as const
import random
import time
if os.name == 'nt': os.system('cls')
if os.name == 'posix': os.system('clear')
rows, columns = os.popen('stty size', 'r').read().split()
Inclination = math.radians(INCLINATION)
Period = PERIOD*const.day
Is there a way where I can put all of this into once single module and just call it? I tried to put all of this into an external program and call it, but as I understood everything gets done, but only locally, not on the main code.
The idea would be to be able to also use this "initialization module" in multiple programs.
Did you try putting all of that into some other .py file, and then just from x import *? Then you should have all of those modules and constants in whatever file you called from.
EDIT: If you're worried about performing all of that multiple times, don't be. On an import, Python checks to see if a module has already been loaded before it goes and loads that module again. For example say we have these files:
fileA.py => from initializer import *
fileB.py => import initializer
fileC.py => import fileA, fileB
When you run fileC.py, the code in initializer.py is only run once, even though both fileA and fileB successfully load it, and even though they do so in different ways.
you don't need any special mechanism. when you import this module then python goes throw it and all values are initialized and you can use it. just import it and this is all.

Python: Is there a place when I can put default imports for all my modules?

Is there a place when I can put default imports for all my modules?
If you want default imports when using the python shell you can also set the PYTHONSTARTUP environmental variable to point to a python file that will be executed whenever you start the shell. Put all your default imports in this file.
Yes, just create a separate module and import it into yours.
Example:
# my_imports.py
'''Here go all of my imports'''
import sys
import functools
from contextlib import contextmanager # This is a long name, no chance to confuse it.
....
# something1.py
'''One of my project files.'''
from my_imports import *
....
# something2.py
'''Another project file.'''
from my_imports import *
....
Note that according to standard guidelines, from module import * should be avoided. If you're managing a small project with several files that need common imports, I think you'll be fine with from module import *, but it still would be a better idea to refactor your code so that different files need different imports.
So do it like this:
# something1.py
'''One of my project files. Takes care of main cycle.'''
import sys
....
# something2.py
'''Another project file. Main program logic.'''
import functools
from contextlib import contextmanager # This is a long name, no chance to confuse it.
....

What are good rules of thumb for Python imports?

I am a little confused by the multitude of ways in which you can import modules in Python.
import X
import X as Y
from A import B
I have been reading up about scoping and namespaces, but I would like some practical advice on what is the best strategy, under which circumstances and why. Should imports happen at a module level or a method/function level? In the __init__.py or in the module code itself?
My question is not really answered by "Python packages - import by class, not file" although it is obviously related.
In production code in our company, we try to follow the following rules.
We place imports at the beginning of the file, right after the main file's docstring, e.g.:
"""
Registry related functionality.
"""
import wx
# ...
Now, if we import a class that is one of few in the imported module, we import the name directly, so that in the code we only have to use the last part, e.g.:
from RegistryController import RegistryController
from ui.windows.lists import ListCtrl, DynamicListCtrl
There are modules, however, that contain dozens of classes, e.g. list of all possible exceptions. Then we import the module itself and reference to it in the code:
from main.core import Exceptions
# ...
raise Exceptions.FileNotFound()
We use the import X as Y as rarely as possible, because it makes searching for usage of a particular module or class difficult. Sometimes, however, you have to use it if you wish to import two classes that have the same name, but exist in different modules, e.g.:
from Queue import Queue
from main.core.MessageQueue import Queue as MessageQueue
As a general rule, we don't do imports inside methods -- they simply make code slower and less readable. Some may find this a good way to easily resolve cyclic imports problem, but a better solution is code reorganization.
Let me just paste a part of conversation on django-dev mailing list started by Guido van Rossum:
[...]
For example, it's part of the Google Python style guides[1] that all
imports must import a module, not a class or function from that
module. There are way more classes and functions than there are
modules, so recalling where a particular thing comes from is much
easier if it is prefixed with a module name. Often multiple modules
happen to define things with the same name -- so a reader of the code
doesn't have to go back to the top of the file to see from which
module a given name is imported.
Source: http://groups.google.com/group/django-developers/browse_thread/thread/78975372cdfb7d1a
1: http://code.google.com/p/soc/wiki/PythonStyleGuide#Module_and_package_imports
I would normally use import X on module level. If you only need a single object from a module, use from X import Y.
Only use import X as Y in case you're otherwise confronted with a name clash.
I only use imports on function level to import stuff I need when the module is used as the main module, like:
def main():
import sys
if len(sys.argv) > 1:
pass
HTH
Someone above said that
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
is equivalent to
import X
import X allows direct modifications to A-P, while from X import ... creates copies of A-P. For from X import A..P you do not get updates to variables if they are modified. If you modify them, you only modify your copy, but X does know about your modifications.
If A-P are functions, you won't know the difference.
Others have covered most of the ground here but I just wanted to add one case where I will use import X as Y (temporarily), when I'm trying out a new version of a class or module.
So if we were migrating to a new implementation of a module, but didn't want to cut the code base over all at one time, we might write a xyz_new module and do this in the source files that we had migrated:
import xyz_new as xyz
Then, once we cut over the entire code base, we'd just replace the xyz module with xyz_new and change all of the imports back to
import xyz
DON'T do this:
from X import *
unless you are absolutely sure that you will use each and every thing in that module. And even then, you should probably reconsider using a different approach.
Other than that, it's just a matter of style.
from X import Y
is good and saves you lots of typing. I tend to use that when I'm using something in it fairly frequently But if you're importing a lot from that module, you could end up with an import statement that looks like this:
from X import A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
You get the idea. That's when imports like
import X
become useful. Either that or if I'm not really using anything in X very frequently.
I generally try to use the regular import modulename, unless the module name is long, or used often..
For example, I would do..
from BeautifulSoup import BeautifulStoneSoup as BSS
..so I can do soup = BSS(html) instead of BeautifulSoup.BeautifulStoneSoup(html)
Or..
from xmpp import XmppClientBase
..instead of importing the entire of xmpp when I only use the XmppClientBase
Using import x as y is handy if you want to import either very long method names , or to prevent clobbering an existing import/variable/class/method (something you should try to avoid completely, but it's not always possible)
Say I want to run a main() function from another script, but I already have a main() function..
from my_other_module import main as other_module_main
..wouldn't replace my main function with my_other_module's main
Oh, one thing - don't do from x import * - it makes your code very hard to understand, as you cannot easily see where a method came from (from x import *; from y import *; my_func() - where is my_func defined?)
In all cases, you could just do import modulename and then do modulename.subthing1.subthing2.method("test")...
The from x import y as z stuff is purely for convenience - use it whenever it'll make your code easier to read or write!
When you have a well-written library, which is sometimes case in python, you ought just import it and use it as it. Well-written library tends to take life and language of its own, resulting in pleasant-to-read -code, where you rarely reference the library. When a library is well-written, you ought not need renaming or anything else too often.
import gat
node = gat.Node()
child = node.children()
Sometimes it's not possible to write it this way, or then you want to lift down things from library you imported.
from gat import Node, SubNode
node = Node()
child = SubNode(node)
Sometimes you do this for lot of things, if your import string overflows 80 columns, It's good idea to do this:
from gat import (
Node, SubNode, TopNode, SuperNode, CoolNode,
PowerNode, UpNode
)
The best strategy is to keep all of these imports on the top of the file. Preferrably ordered alphabetically, import -statements first, then from import -statements.
Now I tell you why this is the best convention.
Python could perfectly have had an automatic import, which'd look from the main imports for the value when it can't be found from global namespace. But this is not a good idea. I explain shortly why. Aside it being more complicated to implement than simple import, programmers wouldn't be so much thinking about the depedencies and finding out from where you imported things ought be done some other way than just looking into imports.
Need to find out depedencies is one reason why people hate "from ... import *". Some bad examples where you need to do this exist though, for example opengl -wrappings.
So the import definitions are actually valuable as defining the depedencies of the program. It is the way how you should exploit them. From them you can quickly just check where some weird function is imported from.
The import X as Y is useful if you have different implementations of the same module/class.
With some nested try..import..except ImportError..imports you can hide the implementation from your code. See lxml etree import example:
try:
from lxml import etree
print("running with lxml.etree")
except ImportError:
try:
# Python 2.5
import xml.etree.cElementTree as etree
print("running with cElementTree on Python 2.5+")
except ImportError:
try:
# Python 2.5
import xml.etree.ElementTree as etree
print("running with ElementTree on Python 2.5+")
except ImportError:
try:
# normal cElementTree install
import cElementTree as etree
print("running with cElementTree")
except ImportError:
try:
# normal ElementTree install
import elementtree.ElementTree as etree
print("running with ElementTree")
except ImportError:
print("Failed to import ElementTree from any known place")
I'm with Jason in the fact of not using
from X import *
But in my case (i'm not an expert programmer, so my code does not meet the coding style too well) I usually do in my programs a file with all the constants like program version, authors, error messages and all that stuff, so the file are just definitions, then I make the import
from const import *
That saves me a lot of time. But it's the only file that has that import, and it's because all inside that file are just variable declarations.
Doing that kind of import in a file with classes and definitions might be useful, but when you have to read that code you spend lots of time locating functions and classes.

Categories