I want to put my interactive commands in a script, but I can't run the same commands in the script.
We are using a heavily packaged version of Python for our tests, we usually run tests in interactive mode, but now I want to place all the commands in a package. Below is an example using the time package.
In interactive mode:
>>> import time
>>> import myscript
In my script:
time.sleep(5)
I expected the script to refer to the globally imported packages and allow me to run sleep, but it says NameError: global name 'time' is not defined
How do I get my script to recognize all packages imported into the interactive terminal? We use thousands of packages in our toolkit, and I can't import them all into my script.
You have to import these libraries also in the .py file where you are going to use them. Python does not allow using them when they are imported in a higher level module, and that's the way it should be. Python, in some way, forces you being better programmer. Your script should be something like this:
import time
time.sleep(5)
If I have Module A:
import time
and Module B:
import A
then in module B I do have access to libraries that A imported, but they must be qualified thus:
A.time.sleep5()
In short, when you import a module, the public names in that module become accessible to the importer. But what you are attempting to do is quite different. In essence, you have Module A as:
import time
import B
And module B as:
time.sleep(5)
Module B neither directly imports the time package nor module A and therefore has no access to time. Being imported by a module that does have access to time does not confer to the imported module that access.
Related
I would like to import a module from inside a functions. For example from this:
from directory.folder.module import module
def import():
app.register_blueprint(module)
To this:
def import():
from directory.folder.module import module
But, without hardcoding it. For example:
def import():
m = "module"
from directory.folder.m import m
Is it possible? Thanks in advance
You want the importlib module.
Here's the most simplistic way to use this module. There are lots of different ways of weaving the results of calls to the module into the environment:
import importlib
math = importlib.import_module("math")
print(math.cos(math.pi))
Result:
-1.0
I've used this library a lot. I built a whole plug-in deployment system with it. Scripts for all the various deploys were dropped in directories and only imported when they were mentioned in a config file rather than everything having to be imported right away.
Something I find very cool about this module is what's stated at the very top of its documentation:
The purpose of the importlib package is two-fold. One is to provide the implementation of the import statement (and thus, by extension, the import() function) in Python source code.
The intro in the 2.7 docs is interesting as well:
New in version 2.7.
This module is a minor subset of what is available in the more full-featured package of the same name from Python 3.1 that provides a complete implementation of import. What is here has been provided to help ease in transitioning from 2.7 to 3.1.
No, python import does not work this way.
Such as an example you try to import a module named mod, so you run import mod. Now interpreter will search for mod.py in a list of directories gathered from the following sources:
The directory from where the input script was run or the current directory if the interpreter is being run interactively.
The list of directories contained in the PYTHONPATH environment variable, if it is set. (The format for PYTHONPATH is OS-dependent but should mimic the PATH environment variable.)
An installation-dependent list of directories configured at the time Python is installed.
So if you have a variable named m='mod' and run import m it will search for m.py not mod.py.
But just a silly dangerous workaround is to use exec() (WARNING FOR MALICIOUS INPUT)
m = "module"
exec(f'from directory.folder.m import {m}')
If you don't mind external modules try importlib.
You can use the importlib module to programmatically import modules.
import importlib
full_name = "package." + "module"
m = importlib.import_module(full_name)
I'm using a from . import module statement to do exactly that: import a local module to my script. The script and module reside in the same folder.
# module.py
def foo():
print('Foo!')
# script.py
from . import module
module.foo()
> ImportError: cannot import name 'module'
This should be pretty easy, and doing just import module does work, but as this answer suggests one should, I modified the statements to the former form.
The end goal is to have a package, from which I can use things, but also to have executable scripts inside the package that import other parts of that package. Apparently, after a few days worth of searching and a few questions I still don't quite understand the import and packaging machinery.
These might be the cause:
Import statements are different in 2.7 and 3.x, I'm using 3.6, the question was on 2.7
Relative imports are different inside packages (folder with __init__.py)
The working directory is different or the folders are not in sys.path
Having an __init__ file does not make a difference at least in a fresh project in PyCharm. Also, the working directory is set to the folder of the sources and it is in path.
Have I missed something? Or rather, what's the correct way of achieving the functionality described in the end goal? Any help is greatly appreciated!
Since writing this answer I have realised it is more convenient and better style in my humble opinion to install the package with pip install -e . and use absolute imports. So even within a package writing from package.sub.module import thing. This makes refactoring a lot easier and there's no need to ever manipulate module variables or sys.path.
When running a script directly, Python consideres the name (a special variable, __name__) of that script to be "__main__". In case of an import, the name is set to the name of the module. In the latter case relative imports are fine. But import actually looks at the combination of __name__ and another special variable, __package__, which is None for an executed script, but the path to a module for an imported module, e.g. parent.sub.
The searched variable is... drumroll...
__package__ + '.' + __name__
The secret ingredient is manipulating __package__:
# script.py
__package__ = 'package_name' # or parent.sub.package
from . import module
This lets Python know you are inside a package even though the script is executed directly. However, the top level folder needs to be in sys.path and the package name has to reflect that directory structure.
See this very comprehensive answer on the topic of relative imports.
If I understand correctly, the python syntax from ... import ... can be used in two ways
from package-name import module-name
from module-name import function-name
I would like to know a bit of how Python internally treats the two different forms. Imagine, for example, that the interpreter gets "from A import B", does the interpreter actually try to determine whether A is a package-name/ module-name, or does it internally treat packages and modules as the same class of objects (something like Linux treats files and directories very similarly)?
First of all, a module is a python file that contains classes and functions. when you say From A Import B python searches for A(a module) in the standard python library and then imports B(the function or class) which is the module if it finds A. If it doesn't it goes out and starts searching in the directory were packages are stored and searches for the package name( A ) and then if it finds it, it imports the Module name(B). If it fails in the past 2 processes it returns an error.
Hope this helps.
I'm confused by the behaviour of importlib in the interactive IPython shell. When I run:
import importlib.reload as ilrel
I get the error ImportError: No module named 'importlib.reload'. This is exactly how I import other modules, such as matplotlib.pyplot.
Currently I've been simply importing importlib alone, then using importlib.reload(<module name>). This isn't a major issue but why does the first method not work?
Because reload is not a module, it's a function within the importlib module. There is nothing specific about importlib; this is how imports work for all modules.
If you just want the function itself, you can do from importlib import reload.
Note also that this function is only available in Python 3.4+.
This question is a bit dumb but I have to know it. Is there any way to use imported modules inside other imported modules?
I mean, if I do this:
-main file-
import os
import othermodule
othermodule.a()
-othermodule-
def a():
return os.path.join('/', 'example') # Without reimporting the os module
The os module is not recognized by the file. Is there any way to "reuse" the os module?
There's no need to do that, Python only loads modules once (unless you unload them).
But if you really have a situation in which a module can't access the standard library (care to explain???), you can simply access the os module within the main module (e.g. mainfile.os, modules are just variables when imported into a module namespace).
If the os module is already loaded, you can also access it with sys.modules["os"].
You have to put import os in othermodule.py as well (or instead, if "main file" doesn't need os itself). This is a feature; it means othermodule doesn't have to care what junk is in "main file". Python will not read the files for os twice, so don't worry about that.
If you need to get at the variables in the main file for some reason, you can do that with import __main__, but it's considered a thing to be avoided.
If you need a module to be reread after it's already been imported, you probably should be using execfile rather than import.
Python only imports a module once. Any subsequent import calls, just access the existing module object.