Where to import modules - python

Lets say I have a module called device which contains a class called ConfigureDevice. Lets also say that I have a module called comports which defines my com ports in a class called ComPorts (enum in C).
Now, lets say that the constructor for ConfigureDevice takes an argument called comPorts. The question is, should I import comports at the beginning of the device module or should the code creating ConfigureDevice make this import?
So, should import comports occur here:
# device module
import serialwriter
import comports
class ConfigureDevice:
def __init__(self, comPort):
self.serialWriter = serialwriter.SerialWriter(comPort)
Or should I import it in the code that creates ConfigureDevice, like this:
import device
import comports
...
device.ConfigureDevice(comports.ComPorts.COM_1)

You should generally always put import at the top of the module, where Python programmers will expect to find it, because then any import errors will happen right when the program starts, instead of happening much later when a function is finally called. We generally only put import inside a function because (a) we are trying to avoid an awkward import loop among badly-designed modules, or (b) because we want to make a 3rd-party library optional so that you only need it if you call that function.
Update: Thank you for the code samples! Beyond my initial advice, that import always go at the top of a file, I can additionally now recommend that you remove the import of comport from your device module because, from what I can see, you never use the module there — I do not see the name comport anywhere in the device module code. In general, if you try removing an import statement from a file but the program still runs, the statement did not belong there in the first place. The pyflakes program can help you find import statements that are no longer useful as your code evolves.

Related

Taking an input from python file to another

I made a file that turns to other files and run their scripts consecutively. Most of these files have a common parameter which is an input. When I import it, it (of course) requests for input. I wish to avoid re-input of something.
Example:
MainFile.py:
import Base_params
import Liner
Base_params.py:
no_of_slices=int(input('Enter no. of Slices'))
sub_slice=int(input('enter sub slice'))
Liner.py:
from PIL import Image
import shutil
from Base_params import no_of_slices, sub_slice
The short answer is that Python handles this for you already exactly the way you want. To understand why, let me give you a little background on the import system.
When a module is imported for the first time, an empty module object is created. Then its code is executed and any names you bind are placed in its dictionary, which is also the global namespace for the module. In your case that would mean running the code of Base_params.py and creating the names no_of_slices and sub_slice based on the user input.
When the same module is imported subsequently, its code is not run (which is your concern). Instead, the object reference from sys.modules is returned. An import statement always checks whether a module is already loaded before attempting to run it again.
The reason that creating the empty module object (and placing it in sys.modules before running the module code is very important is that most modules have recursive imports. Marking the module as already imported ensures that any infinite loops are broken before they happen.
In your case, it is perfectly fine to define a module of constants that asks for user input. The first module that does import Base_params will trigger an execution of the input statements. All further occurrences of import Base_params will just bind sys.modules['Base_params'] to whatever the name Base_params in your namespace. There will not be a second query for no_of_slices and sub_slice.
The links to the official documentation I provided throughout will explain anything I missed.

Importing identically named methods

So I have two separate Python packages that I'm importing into my Python script for Raspberry Pi. In this case as;
from rflib import*
from Rpi.GPIO import*
However, both packages have their own seperate method cleanup(self)
So, at the end of the script when I use the command
cleanup(), how do I a) know which package the method is coming from (they both do utterly different things b) control which one is run?
I've looked into similarly named questions, but which seem to deal with inheritance overloading rather than package imports
from <module> import * takes all names in a module (those that don't start with a _ or everything listed in <module>.__all__ and assigns those names as globals in your current module.
If two modules define the same name, that means that the last one imported this way wins; cleanup = rflib.cleanup is replaced by cleanup = Rpi.GPIO.cleanup with the second from Rpi.GPIO import * statement.
You generally want to avoid using from <module> import *. Import specific names, or just the module itself.
In this case, you can do:
from rflib import cleanup as rflib_cleanup
from Rpi.GPIO import cleanup as rpigpio_cleanup
which would bind those two functions as different names.
Or you could just import the modules:
import rflib
from Rpi import GPIO
which gives you only the rflib and GPIO names, each a reference to the module object, so now you can reference each of the cleanup functions as attributes on those modules:
rflib.cleanup()
GPIO.cleanup()
If you need to use a lot of names from either module, the latter style is preferred because that limits the number of imports you need to do, keeps your namespace clean and un-cluttered, and gives you more context whereever those names are used in your code.
It is not a good practice to use * with import. You should be doing something like:
import rflib
from Rpi import GPIO
# Clean Up 1
rflib.cleanup
#Clean Up 2
GPIO.cleanup()
Additional pice of information:
In case your files/objects are of same name, in that case you should use as with import. For example:
from file1 import utils as file1_utils
from file2 import utils as file2_utils
file1_utils.my_func()
file2_utils.my_func()

reload/reimport a file/class that is imported using from * import *

well, as the title say, i got a group of import, all import a class, all in the same folder as the script running it:
from lvl import lvl
from get import get
from image import image
from video import vid
from video import MLStripper
from system import system
from setting import setting
from listsearch import lists
python3 doesn't have reload iirc but there is imp.reload() but it doesn't seem to work,
it just throw a error saying it not a module (it a class so it doesn't work)
after every little edit in those class that are imported, i would need to restart the script
isn't there a way to reload/reimport the class to show the effect of the edit without needing to start the script or rewriting most of the script so that imp.reload() works?
python3, linux (but prefer if it also work on window)
edit1:
example: if i use:
import system
system.system.temp()
it return:
65°C
if i change it to show °F and reload it using imp.reload
imp.reload(system)
system.system.temp()
it return:
149°F
so, it works BUT if i use
import system as _system
from system import system
system.temp()
it return:
65°C
then i change it to show °F and reload it using imp.reload
imp.reload(_system)
from system import system
system.temp()
it still return
65°C
BUT again, if i call it this way:
_system.system.temp()
it return
149°F
idk why it that but it is cause it happen in a while loop?
edit2:
file name: system.py:
before changing for test:
class system:
def temp():
temperature = open("/sys/class/thermal/thermal_zone0/temp","r").read()
temperature = temperature[:2]
return(temperature+"°C")
after changing for test:
class system:
def temp():
temperature = open("/sys/class/thermal/thermal_zone0/temp","r").read()
temperature = temperature[:2]
temperature = str(9.0 / 5.0 * int(temperature) + 32).split(".")[0]
return(temperature+"°C")
You can only reload a module:
The argument must be a module object, so it must have been successfully imported before.
In your case, you don't have any reference to the module object. You will have to import it, even if you don't want to use it for anything else, just for the sake of calling reload later.
Also, after the reload, you have re-import the names:
Other references to the old objects (such as names external to the module) are not rebound to refer to the new objects and must be updated in each namespace where they occur if that is desired.
When you do from foo import bar, that bar is a "name external to the module", so you have to rebind it explicitly.
If you think about it, it has to work this way. There's no way reload can enumerate all objects whose definition is dependent on the previous version of the module to update them. Even if it could, there could be infinite cycles. And what would happen if the new version didn't even have a definition for a class that was in the old one? Or if the class were defined dynamically?
Looking at it another way, from foo import bar is very similar to import foo; bar = foo.bar. bar is a name in your namespace, not foo's namespace, so reload(foo) will not touch it; you need to copy the new foo.bar over again.
The easy way to solve all of these problems is to just repeat all of your from foo import bar lines after the reload.
For simple cases:
import video
from video import MLStripper
# ... later
imp.reload(video)
from video import MLStripper
However, most of your examples have an obvious naming conflict: once you from video import video, you can no longer reload(video). So, you need another reference to the video module object.
Python keeps one around for you, which you can use:
imp.reload(sys.modules['video'])
from video import MLStripper
Or, alternatively, you can use an as clause, or just an = assignment, to give it whatever name you want.
import video as _video
from video import video
# ... later
imp.reload(_video)
from video import video
From your comments and your edited question, it sounds like you have a further problem. Let's use one of the simple non-colliding cases to discuss it.
I believe you're actually doing something like this:
import video
from video import MLStripper
stripper = MLStripper('foo")
# ... later
imp.reload(video)
from video import MLStripper
The first line will successfully reload the video module, and the second will copy its MLStripper class into your globals, so any new MLStripper instances you created will be of the new type.
But that doesn't affect any existing MLStripper instances, like stripper.
Just like MLStripper was, stripper is one of those "names external to the module". But it's actually even worse. In order to adjust it, reload would have to figure out what its state would have been, had the new version of the code been in effect from the time it was created. It should be obvious that this is an unsolvable problem.
If you know the instances you want to patch up, you can deal with them in effectively the same way you dealt with the classes: just create them again:
imp.reload(video)
from video import MLStripper
stripper = MLStripper('foo")
If that's not good enough, there are three hacky possibilities that may be what you want:
Monkeypatch the methods, attributes, etc. into the instance(s) and their __class__(es).
Patch the instances' __class__ attribute directly, so anything that was inherited from the class will now be inherited from the new class.
Serialize the instances with pickle before the reload, then deserialize after.
For very simple cases, all three of these will work. For more complex cases, you will have to understand what you're doing.
Note that you can wrap a lot of this stuff up in a function, but you have to understand how locals and globals work (and how import and reload work) or you're going to end up confusing yourself.
A simpler solution is to just create "dump all state" and "load all state" functions. Then you can dump everything, quit, relaunch, and restore. The Python tutorial and the ipython docs both describe a few different ways to do this in place of using reload; it's probably worth going back and rereading those.
Access the module through sys.modules, reload that, then reassign the imported names:
imp.reload(sys.modules['lvl'])
from lvl import lvl
imp.reload(sys.modules['get'])
from get import get
etc.
All the from something import name syntax does is import something then bind name to the same object something.name refers to.
By using sys.modules you don't have to explicitly import the module again, and can reach the new definitions of the objects for rebinding after reloading.

How to tell if a Python modules I being reload()ed from within the module

When writing a Python module, is there a way to tell if the module is being imported or reloaded?
I know I can create a class, and the __init__() will only be called on the first import, but I hadn't planning on creating a class. Though, I will if there isn't an easy way to tell if we are being imported or reloaded.
The documentation for reload() actually gives a code snippet that I think should work for your purposes, at least in the usual case. You'd do something like this:
try:
reloading
except NameError:
reloading = False # means the module is being imported
else:
reloading = True # means the module is being reloaded
What this really does is detect whether the module is being imported "cleanly" (e.g. for the first time) or is overwriting a previous instance of the same module. In the normal case, a "clean" import corresponds to the import statement, and a "dirty" import corresponds to reload(), because import only really imports the module once, the first time it's executed (for each given module).
If you somehow manage to force a subsequent execution of the import statement into doing something nontrivial, or if you somehow manage to import your module for the first time using reload(), or if you mess around with the importing mechanism (through the imp module or the like), all bets are off. In other words, don't count on this always working in every possible situation.
P.S. The fact that you're asking this question makes me wonder if you're doing something you probably shouldn't be doing, but I won't ask.
>>> import os
>>> os.foo = 5
>>> os.foo
5
>>> import os
>>> os.foo
5

How do I override a Python import?

I'm working on pypreprocessor which is a preprocessor that takes c-style directives and I've been able to make it work like a traditional preprocessor (it's self-consuming and executes postprocessed code on-the-fly) except that it breaks library imports.
The problem is: The preprocessor runs through the file, processes it, outputs to a temporary file, and exec() the temporary file. Libraries that are imported need to be handled a little different, because they aren't executed, but rather they are loaded and made accessible to the caller module.
What I need to be able to do is: Interrupt the import (since the preprocessor is being run in the middle of the import), load the postprocessed code as a tempModule, and replace the original import with the tempModule to trick the calling script with the import into believing that the tempModule is the original module.
I have searched everywhere and so far and have no solution.
This Stack Overflow question is the closest I've seen so far to providing an answer:
Override namespace in Python
Here's what I have.
# Remove the bytecode file created by the first import
os.remove(moduleName + '.pyc')
# Remove the first import
del sys.modules[moduleName]
# Import the postprocessed module
tmpModule = __import__(tmpModuleName)
# Set first module's reference to point to the preprocessed module
sys.modules[moduleName] = tmpModule
moduleName is the name of the original module, and tmpModuleName is the name of the postprocessed code file.
The strange part is this solution still runs completely normal as if the first module completed loaded normally; unless you remove the last line, then you get a module not found error.
Hopefully someone on Stack Overflow know a lot more about imports than I do, because this one has me stumped.
Note: I will only award a solution, or, if this is not possible in Python; the best, most detailed explanation of why this is not impossible.
Update: For anybody who is interested, here is the working code.
if imp.lock_held() is True:
del sys.modules[moduleName]
sys.modules[tmpModuleName] = __import__(tmpModuleName)
sys.modules[moduleName] = __import__(tmpModuleName)
The 'imp.lock_held' part detects whether the module is being loaded as a library. The following lines do the rest.
Does this answer your question? The second import does the trick.
Mod_1.py
def test_function():
print "Test Function -- Mod 1"
Mod_2.py
def test_function():
print "Test Function -- Mod 2"
Test.py
#!/usr/bin/python
import sys
import Mod_1
Mod_1.test_function()
del sys.modules['Mod_1']
sys.modules['Mod_1'] = __import__('Mod_2')
import Mod_1
Mod_1.test_function()
To define a different import behavior or to totally subvert the import process you will need to write import hooks. See PEP 302.
For example,
import sys
class MyImporter(object):
def find_module(self, module_name, package_path):
# Return a loader
return self
def load_module(self, module_name):
# Return a module
return self
sys.meta_path.append(MyImporter())
import now_you_can_import_any_name
print now_you_can_import_any_name
It outputs:
<__main__.MyImporter object at 0x009F85F0>
So basically it returns a new module (which can be any object), in this case itself. You may use it to alter the import behavior by returning processe_xxx on import of xxx.
IMO: Python doesn't need a preprocessor. Whatever you are accomplishing can be accomplished in Python itself due to it very dynamic nature, for example, taking the case of the debug example, what is wrong with having at top of file
debug = 1
and later
if debug:
print "wow"
?
In Python 2 there is the imputil module that seems to provide the functionality you are looking for, but has been removed in python 3. It's not very well documented but contains an example section that shows how you can replace the standard import functions.
For Python 3 there is the importlib module (introduced in Python 3.1) that contains functions and classes to modify the import functionality in all kinds of ways. It should be suitable to hook your preprocessor into the import system.

Categories