How to import modules regardless of the directory - python

I would like to know if there is any way to be able to use the modules of a project, regardless of the module's path, if it is in one or more directories above the current script
since what I have tried to do is something like this but it doesn't work.
import os
r = os.path.realpath(file.py)
from r import functionR
When I investigated a little more, I found something that talks about adding the modules to the main path, but I don't know if that is correct?
I hope you can help me a little
added an example route i'm using
root
folder1
folder11
file1.py
folder2
folder22
file2.py
file_one.py
For example, try using the file_one.py module in files that are at lower levels, for example file1.py or file2.py
I hope you can help me

you can try adding the directory containing the modules of interest to the sys.path
import sys
sys.path.extend([put_directory_here])
or add the directory to the PATH environment variable
or add the folder containing the modules to a location that is already in the path i.e. site packages
this way python knows where to look for the modules and they will be accessible anywhere
there's also a ton of info about absolute/relative imports of modules here: Relative imports for the billionth time

Related

Use __init__.py to modify sys path is a good idea?

I want to ask you something that came to my mind doing some stuff.
I have the following structure:
src
- __init__.py
- class1.py
+ folder2
- __init__.py
- class2.py
I class2.py I want to import class1 to use it. Obviously, I cannot use
from src.class1 import Class1
cause it will produce an error. A workaround that works to me is to define the following in the __init__.py inside folder2:
import sys
sys.path.append('src')
My question is if this option is valid and a good idea to use or maybe there are better solutions.
Another question. Imagine that the project structure is:
src
- __init__.py
- class1.py
+ folder2
- __init__.py
- class2.py
+ errorsFolder
- __init__.py
- errors.py
In class1:
from errorsFolder.errors import Errors
this works fine. But if I try to do in class2 which is at the same level than errorsFolder:
from src.errorsFolder.errors import Errors
It fails (ImportError: No module named src.errorsFolder.errors)
Thank you in advance!
Despite the fact that it's slightly shocking to have to import a "parent" module in your package, your workaround depends on the current directory you're running your application, which is bad.
import sys
sys.path.append('src')
should be
import sys,os
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)),os.pardir))
to add the parent directory of the directory of your current module, regardless of the current directory you're running your application from (your module may be imported by several applications, which don't all require to be run in the same directory)
One correct way to solve this is to set the environment variable PYTHONPATH to the path which contains src. Then import src.class1 will always work, regardless of which directory you start in.
from ..class1 import Class1 should work (at least it does here in a similar layout, using python 2.7.x).
As a general rule: messing with sys.path is usually a very bad idea, specially if this allows a same module to be imported from two different paths (which would be the case with your files layout).
Also, you may want to think twice about your current layout. Python is not Java and doesn't require (nor even encourage) a "one class per module" approach. If both classes need to work together, they might be better in a same module, or at least in modules at the same level in the package tree (note that you can use the top-level package's __init__ as a facade to provide direct access to objects defined in submodules / subpackages). NB : I'm not saying that your current layout is necessarily wrong, just that it might not be the simplest one.
There is also a solution that does not involve the use of the environment variable PYTHONPATH.
In src/ create setup.py with these contents:
from setuptools import setup
setup()
Now you can do pip install -e /path/to/src and import to your hearts content.
-e, --editable <path/url> Install a project in editable mode (i.e. setuptools "develop mode") from a local project path or a VCS url.
No, Its not good. Python takes modules in two ways:
Python looks for its modules and packages in $PYTHONPATH.
Refer: https://docs.python.org/2/using/cmdline.html#envvar-PYTHONPATH
To find out what is included in $PYTHONPATH, run the following code in python (3):
import sys
print(sys.path)
all folder containing init.py are marked as python package.(if they are subdirectories under PYTHONPATH)
By help of these two ways you can full-fill the need to create a python project.

Better approach to use script inside nested directory PYTHONPATH

Sorry for asking my own question 2nd time, but i am totally stuck in import file in python.
I have a directory structure below:
|--test/foo.py
|--library #This is my PYTHONPATH
|--|--script1.py
|--|--library_1
|--|--|--script2.py
|--|--library_2
|--|--library_3
I am accessing library/library_1/script2.py from test/foo.py.
Here i am confused about what is the better approach. Generally all library folders or utility functions should be added to pythonpath.
This is a folder structure i am maintaining to differentiate utility functions and test scripts.
I tried putting __init__.py in library and library1 & then imported like from library1 import script2, but getting error as No module named script.
I have tried appending that path to system path as well.
Working: if i add another pythonpath like path/to/library/libray_1/. So should i do this for all folders which are inside library folder to make it work ?
Here's what you need to do:
|--test/foo.py
|--library #This is my PYTHONPATH
|--__init__.py
|--|--script1.py
|--|--library_1
|--|--|--__init__.py
|--|--|--script2.py
|--|--library_2
|--|--|--__init__.py
|--|--library_3
|--|--|--__init__.py
And inside the first __init__.py below library you need to do:
import library1
import library2
import script
Then, if library is your python path, you can do this within test/foo.py with no errors:
import library
library.library1.bar()
library.script.foo()

pydev - how to avoid adding sub directories to python path in order to fix unresolved import issue

My project has root src folder created by pydev project wizard. Src folder is in the project's python path. Underneath that folder I have a package (folder with __init__.py) with two files: a.py and b.py. b.py is trying to import from a.py but I'm getting the error of unresolved import.
I was able to "fix" error by explicitly adding that subfolder to project's python path as additional src folder. Now I have two folders as src folders in pythonpath. What I don't understand is, why pydev is not able to resolve import since the package/folder I'm talking about is directly underneath root src folder which is in the python path. There are no python files in root src folder.
If I add __init__.py to root src folder, the issue is still there. I simply have to add subfolder to pythonpath in order to make error go away.
Am I doing something wrong ? This doesn't seem right.
EDIT:
I was wrong. My import syntax was incorrect. I should have done: from package.module import someting and not from module import something
It's hard to tell from your description, and actual code would help, but I suspect what you're looking for is a relative import.
If you have a file pkg/a.py that just does this:
import b
That will look for a top-level module somewhere on your sys.path named b.py.
But if you do this:
from . import b
Then it will look within (and only within) pkg for a file named b.py.
Alternatively, you could use an absolute import, the same way you would in a module outside the package, like one of these:
import pkg.b
from pkg import b
Your attempted workaround of adding pkg to sys.path is a very bad idea, for multiple reasons. For example, b and pkg.b will become different modules as far as Python is concerned, so the top-level code can end up getting run twice, you can end up with two separate copies of all of the globals (and even if you think "I'm not using globals", you probably as—classes and functions are globals, and you can easily end up with a situation where b.MyClass(3) != pkg.b.MyClass(3) unexpectedly, which is always fun to debug…), etc.
Adding an __init__.py to src is also a bad idea. That turns src into a package, meaning the proper qualified name for b is now src.pkg.b, rather than pkg.b, but there's no way to import it under the proper name (unless the parent directory of src happens to be on sys.path as well as src… in which case you have the exact same problem as the above paragraph).
See PEP 328 for more details, and the tutorial section on Packages for a simpler overview.

Access modules from test file

Here is my file structure that I am working with for my application. My problem is that I cannot get my test_ctd.py file to see my ctd.py file.
Here is my directory structure
FileParser
--Parsers
----ctd.py
--tests
----__init__.py
----test_ctd.py
--parse.py
I never used an init.py file and am struggling to understand it, but here is my attempt at adding ctd.py to my path.
import sys
import os.path
d = os.path.dirname(os.path.dirname(os.path.abspath('../../')))
from Parsers import ctd
Also I do not have any code in my parse.py file, but I will be using that to initiate the program. Would I need a init file for that as well so I can import the files from the Parsers folder?
Any help on how to access my files from within this program structure would be appreciated. Eventually it will be running on a web server, not sure if that makes a difference or not...
Thanks!
Parsers and FileParser must contain __init__.py if you want to import something from ctd.py. See Importing modules in Python and __init__.py.
Then, you can import ctd.py from your tests scripts by doing relative imports like from ..Parsers import ctd or by adding FileParser to sys.path and using from Parsers import ctd.
Or, add the directory containing FileParser to sys.path and use from FileParser.Parsers import ctd.
Hope that helps.
You need to make sure Python is actually looking in the right places. You can do this by modifying your PYTHONPATH environment variable to include places where Python packages are found (such as this directory). You'll also need an __init__.py file, to mark the directory as a Python package.
Or, the cheap, hacky way is by modifying sys.path.
import sys
import os
sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(__file__)), 'Parsers'))
import cdt
Move the __init__.py file into Parsers and add the directory FileParser as absolute path to your PYTHONPATH. For example with sys.path.append('full/path/to/FileParser').

Import Python Issues

I've been writing in python for a couple of months now and I've never found a through explanation of how import works. I downloaded this folder with subfolders with python files in them. I'm trying to use one of these files and I'm loosing my mind. How do you properlly import a folder with all the files in it?
Any help would be greatly appreciated.
As written in the python documentation on modules:
If you have a folder sound looking like that :
sound/ Top-level package
__init__.py Initialize the sound package
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
To import all files of effects folder :
from sound.effects import *
Note that to be able to import module, they have to contain an __init__.py file.
First, check to see if the subdirectories have a file named __init__.py file in them. Python will not recognize directories that do not contain these files.
Then, you will have to manually change the PYTHONPATH, which you can find in sys.path. You can find a great example here.
Edit: I'm not 100% sure this is what you were asking for. If you want to import ALL the python files in a directory, you will have to import them one by one. For example, given a directory like so:
parent/
__init__.py
runner.py
example.py
language.py
you would have to type
from parent import runner, example, language
or
from parent import * # this will also import __init__
You have to create a __init__.py file in the directory to make it a package. In this file you import all the symbols from the underlying files.
See http://docs.python.org/tutorial/modules.html (especially part 6.4 Packages) for further notes on that.
The parent folder must be either in PYTHONPATH or the folder path indicated in a file with extension .pth situated in a location in your path, usually in site-packages.
Then your package and all folders inside it from which you have to import need to have a file named __init__. This file can be used for program initialization but as a starting point it can be an empty file.
For example my program folder, situated in C:\python26 has the estructure:
programas\
.....package1\
.........__init__.py
.........module1.py
.........subpackage1\
.............__init__.py
.............module2.py
.....package2\
.........__init__.py
.........module3
.....__init__.py
.....lonelyscript1.py
.....lonelyscript2.py
file site-packages\site.pth contains:
C:\Python26\programas

Categories