python - import only when required? - python

In my case the Python program has some kind of mods and some mods require special imports. If a mode is not activated at startup, these mode-specific imports should not be checked.
The goal is to start the Python program without the imports, when these are not required for the mode.
Even if I move the import to a separate (mode specific) class, which is not called, an import error message comes up.
Can this be implemented at all?
update:
This seems to work, thanks! # amir zareian
if __name__ == '__main__':
if mode:
import testimport
The other option looks a bit more elegant to me, but the import is not recognized, I tried:
class ImportRequired:
def __init__(self):
import testimport
def function(self):
testimport.testcall()

did you try to put that input in if condition ? or in switch case ?
for example :
if (mode1):
import first
and go on

Related

Passing imports to a script from inside an external method

I have kind of a tricky question, so that it is difficult to even describe it.
Suppose I have this script, which we will call master:
#in master.py
import slave as slv
def import_func():
import time
slv.method(import_func)
I want to make sure method in slave.py, which looks like this:
#in slave.py
def method(import_func):
import_func()
time.sleep(10)
actually runs like I imported the time package. Currently it does not work, I believe because the import stays exists only in the scope of import_func().
Keep in mind that the rules of the game are:
I cannot import anything in slave.py outside method
I need to pass the imports which method needs through import_func() in master.py
the procedure must work for a variable number of imports inside method. In other words, method cannot know how many imports it will receive but needs to work nonetheless.
the procedure needs to work for any import possible. So options like pyforest are not suitable.
I know it can theoretically be done through importlib, but I would prefer a more straightforward idea, because if we have a lot of imports with different 'as' labels it would become extremely tedious and convoluted with importlib.
I know it is kind of a quirky question but I'd really like to know if it is possible. Thanks
What you can do is this in the master file:
#in master.py
import slave as slv
def import_func():
import time
return time
slv.method(import_func)
Now use time return value in the slave file:
#in slave.py
def method(import_func):
time = import_func()
time.sleep(10)
Why would you have to do this? It's because of the application's stack. When import_func() is called on slave.py, it imports the library on the stack. However, when the function terminates, all stack data is released from memory. So the library would get released and collected by the garbage collector.
By returning time from import_func(), you guarantee it continues existing in memory once the function terminates executing.
Now, to import more modules? Simple. Return a list with multiples modules inside. Or maybe a Dictionary for simple access. That's one way of doing it.
[Edit] Using a dictionary and importlib to pass multiple imports to slave.py:
master.py:
import test2 as slv
import importlib
def master_import(packname, imports={}):
imports[packname] = importlib.import_module(packname)
def import_func():
imports = {}
master_import('time', imports)
return imports
slv.method(import_func)
slave.py:
#in slave.py
def method(import_func):
imports = import_func()
imports['time'].sleep(10)
This way, you can literally import any modules you want on master.py side, using master_import() function, and pass them to slave script.
Check this answer on how to use importlib.

how to stop the import of a python module

suppose I have a file my_plugin.py
var1 = 1
def my_function():
print("something")
and in my main program I import this plugin
import my_plugin
Is there a way to silently disable this plugin with something like a return statement?
for example I could "mask" the behavior of my_function like this:
def my_function():
return
print("something")
I am wondering if I can do this for the module as a way to turn it on and off depending on what I am trying to do with the overall project. So something like:
return # this is invalid, but something that says stop running this module
# but continue on with the rest of the python program
var1 = 1
def my_function():
print("something")
I suppose I could just comment everything out and that would work... but I was wondering if something a little more concise exists
--- The purpose:
The thinking behind this is I have a large-ish code-base that is extensible by plugins. There is a plugins directory so the main program looks in the directory and runs all the modules that are in there. The use case was just to put a little kill switch inside plugins that are causing problems as an alternative to deleting or moving the file temporarily
You can just conditionally import the module:
if thing == otherthing:
import module
This is entire valid syntax in python. With this you can set a flag on a variable at the start of your project that will import modules based on what you need in that project.

Check name of running script file in module

I have 2 app files with import same module:
#app1.py
import settings as s
another code
#app2.py
import settings as s
another code
I need in module check if running first or second app:
#settings.py
#pseudocode
if running app1.py:
print ('app1')
elif:
print ('app2')
I check module inspect but no idea.
Also I am open for all better solutions.
EDIT: I feel a bit foolish (I guess it is easy)
I try:
var = None
def foo(a):
var = a
print (var)
but still None.
I'm not sure it is possible for an importee to know who imported it. Even if it was, it sounds like code smell to me.
Instead, what you can do is delegate the decision of what actions are to be taken by app1 and app2, instead of having settings make that decision.
For example:
settings.py
def foo(value):
if value == 'app1':
# do something
else:
# do something else
app1.py
from settings import foo
foo('app1')
And so on.
To assign within the function and have it reflect on a global variable. Example:
A.py
var = None
def foo(a):
global var
var = a
def print_var():
print(var)
test.py
import A
A.print_var()
A.foo(123)
A.print_var()
Output:
None
123
Note that globals aren't recommended in general as a programming practice, so use them as little as possible.
I think your current approach is not the best way do solve your issue. You can solve this, too, by modifying settings.py slightly. You have two possible ways to go: either the solution of coldspeed, or using delegates. Either way, you have to store the code of your module inside functions.
Another way to solve this issue would be (depending on the amount of code lines which depend on the app name) to pass a function/delegate to the function as a parameter like this:
#settings.py
def theFunction(otherParemters, callback):
#do something
callback()
#app1.py
from settings import theFunction
def clb():
print("called from settings.py")
#do something app specific here
theFunction(otherParameter, clb)
This appears to be a cleaner solution compared to the inspect solution, as it allows a better separation of the two modules.
It depends highly on the range of application, whether you should choose the first or the second version; maybe you could provide us with more information about the broader issue you are trying to solve.
As others have said, perhaps this is not the best way to achieve it. If you do want to though, how about using sys.argv to identify the calling module?
app:
import settings as s
settings:
import sys
import os
print sys.argv[0]
# \\path\\to\\app.py
print os.path.split(sys.argv[0])[-1]
# app.py
of course, this gives you the file that was originally run from the command line, so if this is part of a further nested set of imports this won't work for you.
This works for me.
import inspect
import os
curframe = inspect.currentframe()
calframe = inspect.getouterframes(curframe, 1)
if os.path.basename(calframe[1][1]) == 'app1.py':
print ('app1')
else:
print ('app2')

Is there an accepted way in Python to import a module from within a function?

I have written a script for XBMC which optionally downloads a dll and then imports a module that depends on that dll if the download was successful.
However, placing the import inside a function generates a Python syntax warning.
Simplified example:
1 def importIfPresent():
2 if chkFunction() is True:
3 from myOptionModule import *
Line 3 generates the warning, but doesn't stop the script. I can't place this code at the start outside of a function because I need to generate dialog boxes to prompt the download and then hash the file once it is downloaded to check success. I also call this same code at startup in order to check if the user has already downloaded the dll.
Is there a different/better way to do this without generating the syntax warning? Or should I just ignore the warning and leave it as is?
Thank you! Using the useful responses below, I now have:
import importlib
myOptionalModule = None
def importIfPresent():
if chkFunction is True:
try:
myOptionalModule = importlib.import_module('modulex')
except ImportError:
myOptionalModule = None
...
importIfPresent()
...
def laterFunction():
if myOptionalModule != None:
myParam = 'something expected'
myClass = getattr(myOptionalModule, 'importClassName')
myFunction = getattr(myClass, 'functionName')
result = myFunction(myClass(), myParam)
else:
callAlternativeMethod()
I am posting this back mainly to share with other beginners like myself the way I learned through the discussion to use the functionality of a module imported this way instead of the standard import statement. I'm sure that there are more elegant ways of doing this that the experts will share as well...
You're not getting the warning for doing an import inside a function, you're getting the warning for using from <module> import * inside a function. Doing a In Python3, this actually becomes a SyntaxError, not a SyntaxWarning. See this answer for why wildcard imports like this in general, and expecially inside functions are discouraged.
Also, this code isn't doing what you think it does. When you do an import inside a function, the import only takes affect inside the function. You're not importing that module into the global namespace of the file, which I believe is what you're really trying to do.
As suggested in another answer importlib can help you here:
try:
import myOptionModule as opt
except ImportError:
opt = None
def importIfPresent():
global opt
if chkFunction() is True:
opt = importlib.import_module("myOptionModule")
I beleive you need to use the importlib library to facilitate this.
The code would be at the top of the mod:
import importlib
then replace "from myOptionModule import *" with "module = importlib.import_module(myOptionModule)". You can then import the defs/classes you want or import them all by using getattr(module,NAME(S)TOIMPORT).
See if that works.
Check out chapter 30 and 31 of Learning Python by Lutz for more info.

eclipse,python, NameError: name <MyModule> is not defined

I create the following package in eclipse via PyDev:
class Repository(object):
'''
classdocs
'''
def __init__(self):
'''
Constructor
'''
print("salaam")
class Materials(Repository):
'''
'''
def __init__(self):
'''
constructor
'''
My main file is:
if __name__ == '__main__':
pass
import repository;
x = Repository();
When i run my application, i get the following error:
x = Repository();
NameError: name 'Repository' is not defined
Of course, i got a warning on importing my module.
I know my import and relation of my main file and my package or eclipse configuration have problem.
first of all, when you import like this, you can only refer to your class as either repository.Repository or repository.repository.Repository, depending on the whether you import the module or the package.
second, what you import depends on where eclipse thinks you are. You can check that with
import os
print(os.pwd)
at the top of your main script.
third, if you want to import your package like this, you should put it in your search path. You can do that by placing it in site-packages, or for instance by adding
import sys
import os
sys.path.append(os.path.abspath(__file__))
at the top of your main script
additionally, you might want to avoid confusion by giving your module a different name than the package (or the other way round)
(and a little nitpick: __init__ is not the constructor, merely an initializing routine).
The import is wrong.
Instead of
import repository
you want to write for your case:
from repository.repository import Repository
As for PyDev giving the error, it's correct at this point and when you fix your code it should stop complaining.

Categories

Resources