How can I skip intermediate folders in Python imports?
Asked Answered
D

2

7

My python app has a folder structure like this:

my_repo/
  src/
    main.py
    util/   <-- util is a git submodule
      src/
        torgle.py
      test/
        test_torgle.py
  test/
    test_main.py

Inside main.py, I can import stuff in my util submodule like this:

from util.src.torgle import Torgler

But src/ is just a way to keep things organized in my git submodule repo, and shouldn't really be a logical part of the package name inside the main repo. Is there some way I can skip the src part of the module import? I'd rather do this:

from util.torgle import Torgler

I.e. can I essentially alias util/src folder to the Python util package?

(Note that in my real case I have more deeply nested packages (util.x.y.z.torgle), so from util import torgle; torgle.Torgler(...) won't scale well. I'm specifically interested in from util.torgle import Torgler.)

Diary answered 30/3, 2020 at 21:2 Comment(3)
Is there any reason why you build the Python app directly from the repositories, instead of, say, installing it and merging the repository directories in the process?Ales
@MisterMiyagi I'm no Python expert -- could you say more about what you mean by "installing it"? To clarify my situation, both my_repo and util are my own repositories; util is shared between several projects. So if there's a better way to manage that (and still allow me to import from util like from util.torgle ...), I'm definitely flexible.Diary
Are you aware of setup.py or PYTHONPATH? Basically you can merge your code into one single, installable package, or adjust how Python loads modules.Ales
E
1

You can kind of do this by adding my_repo/src/util/__init__.py and adding the following line to it:

from .src import torgle

You'll then be able to do the following:

from util import torgle
torgle.Torgler(...)
Essex answered 30/3, 2020 at 21:38 Comment(1)
Works great, but unfortunately for just one level as shown here. In my real case I have more deeply nested packages (util.x.y.z.torgle), so I believe with this technique I would have to do from util import x; x.y.z.torgle.Torgler(...), right? So I'm specifically interested in getting from util.torgle import Torgler to work. I've updated the question to clarify that.Diary
P
1

My solution is based on an OS trick, while the one of Benjamin Rowell is python specific and very elegant. I suggest taking a look at it first.


The solution are the symbolic links

Explanation

Your situation should be the following:

Directory tree

Where the actual library is within useless_dir, but you want to access it directly.

If you want to import library.py from the main file, the standard way is:

from useful_dir.useless_dir.library import p_func

p_func()

Then, when you call main.py:

python3 main.py  # Hello World!

Here's the trick you are searching for:

1) Place yourself within the useful_dir folder: Useful directory

2) From within this directory create a symbolic link:

ln -s useless_dir/library.py any_name_for_the_library.py

3) Change accordingly the main content:

from useful_dir.any_name_for_the_library import p_func

p_func()

The end

Piscatory answered 30/3, 2020 at 21:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.