How to import packages from inside another package - python

So, I am making an application in python where i am inside a package, and i want to a import a package from outside that older. I have tried os.chdir() but that doesn't work. I have tried to import it by simply saying
I expect the package to be imported and any file that i want can be used as many times as possible so that i can have a more structed program, and easier to understand

My username is too new to comment so I'll indirectly answer, if your UserData is a module (given there is an __init__), and so too is SignLoginLogic, and they are at the same directory level, I have never seen a case where you're importing using your requested method (importing somehow from another module's __init__.py directly). See https://docs.python.org/3/reference/import.html. You should be importing SignLoginLogic into your module using something like from SignLoginLogic import WhatYouWantFromIt or otherwise a relative import.

Related

Importing other python packages in __init__.py

I would like to know if importing packages like pandas or NumPy, which can be the basic need for many modules of a package, should be imported in init.py? If not, can anyone please tell how they should be imported, rather than importing them in each module of a package?
No, you should import them in each python file you need them in.
The init is used, when you want to use your module in another project and want want to make the modules classes, functions, etc. available for outside the module

Python: how to ensure your code won't be accidentally imported by the libraries you use?

A few hours ago I was careless enough to name my short script as code.py. Apparently, there is such a package which is used e.g. by ptvsd or pdb. This led to my code.py to be imported instead and caused a bunch of nested unhandled exceptions with missing imports upon trying to debug my code. What was making it more frustrating is that traceback didn't show any sign of importing my code.py file, so I spent quite a while to find the source of the problem.
I'd like to avoid such situations in the future, so my question is: what's the best practice to ensure that the modules you use aren't importing your code by mistake due to such a name collision?
This is a common gotcha, and actually there's no failsafe way to avoid it. At least you can make sure your modules all live in packages (at least one package if that's a small project with no reusable code) so that you'd use them as from mypackage import code instead of import code (also make sure you use either absolute imports etc), and that you always run your code from the directory containing the package(s), not from within the package directory itself (python inserts the current working directory in first position of sys.path).
This won't prevent ALL possible name masking issues but it should minimize them. Now from experience, once you've experienced this kind of issues at least once, you usually spot the symptoms very quickly - the most common and quite obvious being that some totally unrelated stlib or third-part module starts crashing with ImportErrors or AttributeErrors (with "module X has no attribute Y" messages). At this point, if you just added a new module to your own code, chances are it's the new module that breaks everything, so you can just rename it (make sure you clean up .pyo/.pyc files if any) and see if it solves the issue. Else check the traceback to find out which imports fails, most of the time you'll find you have a module or package by the same name in your current working directory.
You can't avoid completely, that somebody is able to import your module by mistake.
You can structure your code better in subpackages going from "well known" to "less known" names. E.g. if you are developing code for a certain company then you might want to structure like:
company.country.location.department.function
If your code is then getting more accepted and used by others, you can bring the code in the upper namespace, so that it is made available in company.country.location.department.function
and company.country.location.department
You can modify sys.path at the beginning of your main module, before you start importing other modules:
import sys
sys.path.append(sys.path.pop(0))
so that the main module's starting directory is placed at the last of the module search paths rather than at the front, in order for other modules of the same name to take precedence.
EDIT: To all the downvoters, this answer actually works.
For example, running code.py with the following content:
import pdb
pdb.run('print("Hello world")')
would raise:
AttributeError: module 'pdb' has no attribute 'run'
because code.py has no run defined, while running code.py with the following content instead:
import sys
sys.path.append(sys.path.pop(0))
import pdb
pdb.run('print("Hello world")')
would execute pdb.run properly:
> <string>(1)<module>()
(Pdb)

Importing user defined modules in python from a directory

I'm trying to import a module I wrote in python that just prints out a list containing numbers. The issue I'm having is that I want to be able to import it from a separate directory but the answers I have read so far don't seem to be working for my situation.
For example, given I want to import printnumbers.py from a directory in my documents folder I am supposed to implement the following:
import sys
sys.path.append('/home/jake/Documents')
import printnumbers.py
This snipit of code results in a "Import error" telling me that the specified module does not exist. I'm not exactly sure where to proceed from here, I have checked multiple times to make sure it's the right spelling for the path as well as for the module name. I'm still trying to understand exactly what appending to the "sys.path" does. From what I understand it's telling the program to search for modules in that directory?
Thanks for anyone who answers my rather novice question. I'm just looking for a better understanding of it that the python documentation isn't providing for my frame of mind.
When the file is printnumbers.py, the module is called printnumbers (without the .py). Therefore use
import printnumbers
import sys
sys.path.append('/home/jake/Documents')
appends '/home/jake/Documents' to the end of sys.path. The directories listed in sys.path are searched (in the order listed) whenever an import statement causes Python to search for a module. (Already imported modules are cached in sys.modules, so Python does not always need to search sys.path directories to import a module...)
So if you have a file /home/jake/Documents/printnumbers.py, then import printnumbers will cause Python to import it provided there is no other file named printnumbers.py in a directory listed in sys.path ahead of /home/jake/Documents/.
Note that injecting directories into sys.path is not the usual way to set up Python to search for modules. Usually it is preferable to add /home/jake/Documents to your PYTHONPATH environment variable. sys.path will automatically include the directories listed in the PYTHONPATH environment variable.
and one more thing, use an empty __ init __.py file in you directory
to make it as a python package (only then Python will know that this
directory is a Python package directory other than an ordinary
directory). Thus you can import modules from that package from
different directory.

How do I structure my Python project to allow named modules to be imported from sub directories

This is my directory structure:
Projects
+ Project_1
+ Project_2
- Project_3
- Lib1
__init__.py # empty
moduleA.py
- Tests
__init__.py # empty
foo_tests.py
bar_tests.py
setpath.py
__init__.py # empty
foo.py
bar.py
Goals:
Have an organized project structure
Be able to independently run each .py file when necessary
Be able to reference/import both sibling and cousin modules
Keep all import/from statements at the beginning of each file.
I Achieved #1 by using the above structure
I've mostly achieved 2, 3, and 4 by doing the following (as recommended by this excellent guide)
In any package that needs to access parent or cousin modules (such as the Tests directory above) I include a file called setpath.py which has the following code:
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath('...'))
Then, in each module that needs parent/cousin access, such as foo_tests.py, I can write a nice clean list of imports like so:
import setpath # Annoyingly, PyCharm warns me that this is an unused import statement
import foo.py
Inside setpath.py, the second and third inserts are not strictly necessary for this example, but are included as a troubleshooting step.
My problem is that this only works for imports that reference the module name directly, and not for imports that reference the package. For example, inside bar_tests.py, neither of the two statements below work when running bar_tests.py directly.
import setpath
import Project_3.foo.py # Error
from Project_3 import foo # Error
I receive the error "ImportError: No module named 'Project_3'".
What is odd is that I can run the file directly from within PyCharm and it works fine. I know that PyCharm is doing some behind the scenes magic with the Python Path variable to make everything work, but I can't figure out what it is. As PyCharm simply runs python.exe and sets some environmental variables, it should be possible to clone this behavior from within a Python script itself.
For reasons not really germane to this question, I have to reference bar using the Project_3 qualifier.
I'm open to any solution that accomplishes the above while still meeting my earlier goals. I'm also open to an alternate directory structure if there is one that works better. I've read the Python doc on imports and packages but am still at a loss. I think one possible avenue might be manually setting the __path__ variable, but I'm not sure which one needs to be changed or what to set it to.
Those types of questions qualify as "primarily opinion based", so let me share my opinion how I would do it.
First "be able to independently run each .py file when necessary": either the file is an module, so it should not be called directly, or it is standalone executable, then it should import its dependencies starting from top level (you may avoid it in code or rather move it to common place, by using setup.py entry_points, but then your former executable effectively converts to a module). And yes, it is one of weak points of Python modules model, that causes misunderstandings.
Second, use virtualenv (or venv in Python3) and put each of your Project_x into separate one. This way project's name won't be part of Python module's path.
Third, link you've provided mentions setup.py – you may make use of it. Put your custom code into Project_x/src/mylib1, create src/mylib1/setup.py and finally your modules into src/mylib1/mylib1/module.py. Then you may install your code by pip as any other package (or pip -e so you may work on the code directly without reinstalling it, though it unfortunately has some limitations).
And finally, as you've confirmed in comment already ;). Problem with your current model was that in sys.path.insert(0, os.path.abspath('...')) you'd mistakenly used Python module's notation, which in incorrect for system paths and should be replaced with '../..' to work as expected.
I think your goals are not reasonable. Specifically, goal number 2 is a problem:
Be able to independently run each .py file when neccessary
This doesn't work well for modules in a package. At least, not if you're running the .py files naively (e.g. with python foo_tests.py on the command line). When you run the files that way, Python can't tell where the package hierarchy should start.
There are two alternatives that can work. The first option is to run your scripts from the top level folder (e.g. projects) using the -m flag to the interpreter to give it a dotted path to the main module, and using explicit relative imports to get the sibling and cousin modules. So rather than running python foo_tests.py directly, run python -m project_3.tests.foo_tests from the projects folder (or python -m tests.foo_tests from within project_3 perhaps), and have have foo_tests.py use from .. import foo.
The other (less good) option is to add a top-level folder to your Python installation's module search path on a system wide basis (e.g. add the projects folder to the PYTHON_PATH environment variable), and then use absolute imports for all your modules (e.g. import project3.foo). This is effectively what your setpath module does, but doing it system wide as part of your system's configuration, rather than at run time, it's much cleaner. It also avoids the multiple names that setpath will allow to you use to import a module (e.g. try import foo_tests, tests.foo_tests and you'll get two separate copies of the same module).

Correct way to reference files within same module

I'm using this code in one of my apps in Google App Engine. I encountered problems with the way that individual files are referenced. For example, in __init.py__ the files decorators.py, errors.py, etc are imported as follows:
import reddit.decorators
import reddit.errors
import reddit.helpers
import reddit.objects
Since the files are all within the same module, shouldn't they be imported like this instead:
import decorators
import errors
import helpers
import objects
The absolute reference works only if the reddit package is on the system path, which seems not to be the case in Google App Engine, for some reason.
Is this a problem with the source, or do I need to examine my application configuration within Google App Engine more closely?
If you want to use a package, you will have to install the whole directory somewhere where Python can find it, i.e., to a directory that is in sys.path. You should never attempt to use the package contents as standalone modules, since this is not how the package is designed for.
Since the working directory of your main script (.) is in sys.path, you should be able to use the reddit package simply by putting the whole package directory within the same directory as your main script. If you cannot import reddit in Google App Engine, you will have to check your setup there. Unfortunately, I do not know how GAE works or what you are allowed to install there, but I guess it should work, since they allow you to put arbitrary Python modules and packages to your webspace, don't they?
Concerning your original question, you are refering to the wrong section of the manual. For intra-package references, you should either use absolute imports:
import reddit.decorators as decorators
or relative ones:
from . import decorators
If the absolute import syntax works depends on your Python version. This is ambiguous:
import decorators
Do you mean a global module (/decorators.py)? Or a module within the package (/reddit/decorators.py)? Python 2.x will look for a relative import first, then try an absolute import if the relative one fails. Starting with version 2.6, using absolute-style imports is deprecated and should not be used any more. Since 3.0, the statement above will only be interpreted as absolute import and not look for a relative one. Explicit absolute imports will work as expected in both versions.

Categories

Resources