Python Relative Imports but I copied the documentation - python-3.x

I read all the other SO posts about this and it either doesn't work or uses sys.path.append.
Below is a replica of the official documentation:
All other files not shown are empty
moduleA.py
from ..subB.moduleB import MyClass
moduleB.py
class MyClass:
def __init__(self):
pass
package/subB/__init__.py
from .moduleB import MyClass
Traceback from running moduleA.py
Traceback (most recent call last):
File "path\to\my\projects\folder\package\subA\moduleA.py", line 1, in <module>
from ..subB.moduleB import MyClass
ImportError: attempted relative import with no known parent package
File Structure

The Python docs unfortunately forget to mention that their example only works if you run your code in a very specific way using the '-m' switch. So you would have to do python -m subA.moduleA and you need to ensure that your current working directory is package. Otherwise it will fail.
If you don't like these restrictions (like me), I've created an experimental import library: ultraimport
It gives you more control over your imports and lets you do file system based imports.
In moduleA.py you could then write:
import ultraimport
MyClass = ultraimport('__dir__/../subB/moduleB.py', 'MyClass')
This will always work, no matter how you run your code or what is your current working directory. Also no need to change sys.path. It will actually go to the file system and load the very file you've specified.

Related

Is it possible to import CPython variables without PyPy module conflicts

I have a script that is using CPython and has pywin32 modules win32gui, and win32con. I have a variable that I want to import from this script into a different PyPy script to use its value.
It looks something like this:
from functions import var1
however when I try to run this code I get the error
Traceback (most recent call last):
File "d:/folder/functions.py", line 5, in <module>
import win32gui, win32con
ModuleNotFoundError: No module named 'win32gui'
All I need is the value of the variable which is an integer, in any way possible. I think I could perhaps make a function that wraps the value of the variable and send it to the script that way, but I think that might be inefficient.
Is there someway, to avoid module conflicts like this when using different interpreters for different scripts?
You can do something like
try:
import win32gui, win32con
except ImportError:
win32gui = None
wn32con = None
then later in your code, where you use these imports, check if they are None first.

Import don't run in python

I am developing a Django project and I am trying to run a test file but an error in the import occurre.
My folder hierarchy to be like the image:
see the image of function process_data inside of core.py
I am in the test directory trying to run my test file.
My import to be like the code:
from coordenadas.core import process_data
but, when I run my code an error is showed:
Traceback (most recent call last):
File "tests_class_moviment.py", line 1, in <module>
from coordenadas.core import process_data
ModuleNotFoundError: No module named 'coordenadas'
I am tryed use relative import
from .coordenadas.core import process_data
from .core import process_data
from ..coordenadas.core import process_data
from ..core import process_data
but the only way that no error is showed in pycharm is the
from coordenadas.core import process_data
Some idea how can I solve it?
On a partially unrelated note, absolute imports are definitely recommended over relative imports. PEP8:
Relative imports for intra-package imports are highly discouraged. Always use the absolute package path for all imports. Even now that PEP 328 [7] is fully implemented in Python 2.5, its style of explicit relative imports is actively discouraged; absolute imports are more portable and usually more readable.
As for the module error itself, adding an __init__.py file to the "coordenadas" directory will turn it into a module, which is exactly what you need.

Import script in sub directory not working... Blender Add-On

I have a folder structure like this:
C:
|_Blueprint
│ main.py
│
└───toolbox
blueprint_tools.py
When I run this code in Blender's scripting text page:
from toolbox.blueprint_tools import dimension, array, modify
I get an error in the console
Traceback (most recent call last):
File "\main.py", line 20, in <module>
ModuleNotFoundError: No module named 'toolbox'
Error: Python script failed, check the message in the system console
I swear, when I run this code (on other projects) outside of Blender this structure and code runs fine. But I get an error when running this script in Blender for testing out my Add-On.
If I compile the Blueprint folder into a .zip and install it everything works fine.... ??
I'm lost, could anyone please help me.
If I run the code like this: (added a . before toolbox for CWD)
from .toolbox.blueprint_tools import dimension, array, modify
Traceback (most recent call last):
File "\main.py", line 20, in <module>
ImportError: attempted relative import with no known parent package
Error: Python script failed, check the message in the system console
Both your error traces write File \main.py ... which means that Blender considers your main.py file to be in the root folder, knowing nothing about its real location in the file system hierarchy.
When you installed your structure as a zip file, you provided all necessary info to Blender.
Addendum:
Temporarily, during developing / debugging your add-on, you may add the full path (for finding your toolbox.blueprint_tools module) to the sys.path variable.
There are 2 possibilities how to do it:
Insert into your main.py file these commands (use the path to your parent folder of your toolbox folder, of course):
import sys
sys.path += [r"C:\Users\Davi\Documents\Python\PARENT_of_toolbox"]
before your statement
from toolbox.blueprint_tools import dimension, array, modify
command, or
Insert into your main.py file these commands (use the path to your toolbox folder, of course):
import sys
sys.path += [r"C:\Users\Davi\Documents\Python\PARENT_of_toolbox\toolbox"]
before your modified statement
from blueprint_tools import dimension, array, modify

Python - importing other python programs as libraries

I am using FreeCAD.
FreeCAD offers many libraries as .so files.
Therefore, to use them, i just have to modify .bashrc, in order to include in the PYTHONPATH, the location of the library files.
Then it is all a matter of doing import FreeCAD and this works.
This is all vanilla right now.
However, there is another library that i cannot import.
When i type import Draft, i get that
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'Draft'
I looked up and there is no Draft.so in the library directory.
However, in the program's GUI - python console when i type import Draft it works.
I investigated why this happens. I typed:
import Draft
import inspect
inspect.getfile(Draft)
And i got:
'/usr/share/freecad-daily/Mod/Draft/Draft.py'
This is another directory.
There is even another folder in this directory, that contains all the Draft function calls, as separate python files.
(For example there is a method called Draft.scale(). Inside the directory there is a file called scale.py)
Is there a way to include all these python files, so i can use import Draft, and just works?
Perhaps is it a matter of setting a new PYTHONPATH?
Just add '/usr/share/freecad-daily/Mod/Draft' to your PYTHONPATH
In general, each subdir inside Mod is a package root.

How to create package in python 3.5.1?

I have tried to create a package using python 3.5.1 , but got the error when i import the package.
Traceback (most recent call last):
File "Pack.py", line 2, in
import Com
File "C:\Users\admin\Document\Python\packages\Com__init__.py",
line 2, in
from Algebra import *
ImportError: No module named 'Algebra'
To import a package you created named Algebra, your folder structure should look similar to this:
C:\Users\admin\Document\Python\packages\
Com__init__.py
Algebra\
__init__.py
.
.
.
Alternatively, you can put the Algebra packages parent directory on python's sys.path.
You'll likely run into another issue once you resolve this, which is you cannot import * from the Algebra package without specifying the all trait in Algebra's init.py file. Specifying this done like the following, but replacing the values of the list with your module names:
__all__=['add', 'subtract', 'multiply']
Source: https://docs.python.org/3/tutorial/modules.html#packages

Resources