Python Forum
Importing packages with long names
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Importing packages with long names
#1
So I've never really sorted out a good solution to this issue, and from what I can see, there really isn't one. so I thought I'd post here as a last ditch effort to settle the issue.

The problem is this:

I am writing a series of python modules which serve as extensions / plugins for an application. The application adds modules located in the user's /Mod directory to it's environment path on startup. However, the application uses the *second* directory in the hierarchy as the top-level name for the package.

So the structure looks like this:

/Mod
  |--my_extension_first
       |--my_extension_second
            |--__init__.py
            |--my_extension_code.py
Accessing the extension directly from within the application's python console, then, would work by calling:

from my_extension_second import my_extension_code
But, if I want to access the modules from within another module (say, in another extension), I'd have to use:

from my_extension_first.my_extension_second import my_extension_code


The issue, then, is I have to maintain this structure for the sake of the application, but it forces me to pollute the import statements with extra long names.

Of course, I can't just alias the import, e.g.:

import my_extension_first.my_extension_second
my_ext = my_extension_first.my_extension_second
from my_ext import my_extension_code
So is there a way to more cleanly manage something like this? Some other way to alias a package path that I haven't discovered?
Reply
#2
(Nov-06-2019, 01:01 PM)joel_graff Wrote: it forces me to pollute the import statements with extra long names.

I'm not seeing the problem here. How do long names 'pollute' your import statements? They won't be causing any performance problems. Are they causing maintenance problems because you have to do the imports in multiple places?
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
I suppose it's just a coding preference - it's lot of extra typing for no real value in terms of readability - just creates visual 'garbage', so to speak. I'm an 80-character/line guy, so it's a noticeable annoyance especially for me.

It's a purely aesthetic issue, but it bothers me enough to post about it because these are imports that recur frequently across multiple files and may occur multiple times in a single file...
Reply
#4
You can give the import a name:
from my_extension_first.my_extension_second import my_extension_code as my_ext

# or
import my_extension_first.my_extension_second.my_extension_code as my_ext
Then you can use my_ext.

You see this often in other libraries:
import pandas as pd
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
(Nov-06-2019, 01:01 PM)joel_graff Wrote:
import my_extension_first.my_extension_second
my_ext = my_extension_first.my_extension_second
from my_ext import my_extension_code

Hi!

I'm just a newbie, so I'm not sure if this could help you ...

I've seen for instance:

import numpy as np
so maybe you could try something similar (I have no idea if it is going to work or not):

import my_extension_first.my_extension_second as mefmes
All the best,

(Nov-06-2019, 03:26 PM)DeaD_EyE Wrote: You can give the import a name:

Oops! Sorry, DeaD_EyE. It seems that I'm very slow at typing and posting ... shadowing other answers (by 'shadowing' I mean producing something at almost the same time).

All the best,
newbieAuggie2019

"That's been one of my mantras - focus and simplicity. Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it's worth it in the end because once you get there, you can move mountains."
Steve Jobs
Reply
#6
What i do is to lift sub modules and bind package together,so can have one simple main import.
This can all be done in top level __init__.py .
This avoid long import statement and can make package easier to use for end users.
Example:
mod_pack\
|-- __init__.py
|-- my_extension_first.py
  my_extension_second\ 
    |-- my_extension_code.py

# __init__.py
from .my_extension_first import first
from .my_extension_second.my_extension_code import second
# my_extension_first.py
def first():
    return 'Now in first extension code'
# my_extension_code.py
def second():
    return 'Now in second extension code'
Test package:
>>> import mod_pack

>>> mod_pack.first()
'Now in first extension code'

>>> mod_pack.second()
'Now in second extension code'
Or:
>>> from mod_pack import first, second

>>> first()
'Now in first extension code'
>>> second()
'Now in second extension code'
This also work,but don't need your uses to navigate your whole tree to get to code Wink
>>> import mod_pack 

>>> mod_pack.my_extension_second.my_extension_code.second()
'Now in second extension code'
Other examples in these post1, post2.

See that i only use one __init__.py
From Python 3.3+ supports Implicit Namespace Packages that allows to create a package without an __init__.py file.
This however only applies to empty __init__.py files.
So empty __init__.py files are no longer necessary and can be omitted.
Reply
#7
Quote:What i do is to lift sub modules and bind package together,so can have one simple main import.
This can all be done in top level __init__.py .
This avoid long import statement and can make package easier to use for end users.

It's a neat solution, but it, unfortunately, breaks the structure I must maintain.

That is, the my_extension_first/ *must* be the top-level directory. The actual package is contained in my_extension_second/. Without that explicit structure, the application won't be able to load the code.

Thus, the structure I outlined in my original post is unchangeable, and I can't add a __init__.py file to my_extension_first/, since another modules will inevitably have the same structure and, therefore, hide any previous module.

Of course, creating a name to shorten the import (as suggested in the other replies) doesn't work at all, but it perfectly describes the solution I'm trying to find...

I suspect there's really no solution to this - it was worth a shot. :)
Reply
#8
(Nov-08-2019, 02:12 PM)joel_graff Wrote: It's a neat solution, but it, unfortunately, breaks the structure I must maintain.
No it dos not beak anything,the tree dos not get touch.
Can lift sub modules or have full path it's all up to you.
What this is about to make it is easier for users of package,you can keep the structure you want on the back-end.
Maybe your package design is not so good if coupling is to tight or names to long.

To use Requests as example.
One main import import requests and 90 % of the most used tool(get,post,session,json...ect) is on top level and easy to access.
>>> import requests
>>> 
>>> requests.get
<function get at 0x0117D660>

>>> requests.post
<function post at 0x01192300>

>>> requests.sessions()
<module 'requests.sessions' from .... sessions.py'>

>>> requests.status_codes
<module 'requests.status_codes' from ... status_codes.py'>
Eg if back-end tree structure was requests/web/tool/post.
It would be annoying to use this import:
requests.web.tool.post
When post and get should be together,so here could lift post up.

For lesser used tool then have to navigate a little eg utils tool.
>>> import requests
>>> 
>>> requests.utils.guess_json_utf
<function guess_json_utf at 0x0116D738>

>>> requests.utils.codecs.ascii_decode
<built-in function ascii_decode>
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020