7

I'm working on a Python project (Project A) that uses another project from GitHub (Project B). I'm not a Git expert, so after a quick research, I found out that I should use the Project B as a git submodule.

So, I cd project_A_root and did the following:

git submodule add project_B
git submodule init
git submodule update

Now, my project structure looks like this:
enter image description here

In main.py file, I've imported a method from do_something.py.

main.py

from ProjectB.do_something import foo

However, do_something.py file imports a method from util.py file, and that's where the problem occurs.

do_something.py

from util import bar

Project B is a submodule and it assumes that Project B dir is the root of the project, so method from util.py in do_something.py is imported without specifying the package, and I'm getting an error:

ImportError: cannot import name 'bar' from 'util'

Instead, it should be imported like this:

from ProjectB.util import bar

I'm not sure what is the best way to handle this. I've fixed imports in submodule manually, but I cannot push that changes to Git because that's not how the submodules work, so if anyone wants to clone Project A, they must fix imports manually too.

Any help is welcome.

1
  • 1
    "…I found out that I should use the Project B as a git submodule." No, you shouldn't. You should use a proper dependency/package management. See stackoverflow.com/a/54155860/7976758 Commented Feb 13, 2021 at 13:38

3 Answers 3

4

Try this in the head of main.py:

import sys
sys.path.append("ProjectB")

#### your old code ###
....
Sign up to request clarification or add additional context in comments.

1 Comment

I saw that solution with sys.path.append, but at first I've added that to do_something.py... It works when I add that to main.py.
2

ProjectB should have an __init__.py file in its top-level directory. Having one would mean it would be recognised as a package, and the files within ProjectB could import other files from within ProjectB.

do_something.py would be able to import util by using:

from .util import bar

The . before util is interpreted to mean "from the top-level of this package", and because there's a __init__.py file in the ProjectB directory, Python would know that that's the top-level folder being referred to. This means that whatever you named the ProjectB directory, or where you moved it, the files inside it would not need to change their import statements.

You'd still import foo from main by doing

from ProjectB.do_something import foo.

If you can edit ProjectB or raise an issue with the developers of ProjectB, they may be able to add this for you.

Hope this helps.

2 Comments

Just to summarize this approach, which doesn't require changing the system path: (1) all code imports local to a submodule should be relative, (2) all modules using submodules can continue using absolute imports.
Does this work differently between python 2.7 and 3.8? I'm working on some old code and I'm trying to figure out why this fix works me (and why the old code doesn't appear to need this fix)
1

Git is just a version control system. Unfortunately, you can't handle this correctly. The possible solution is patching sys.path variable by adding the ProjectB directory, but this is hack. The best you can do is to use a Python packaging system, to package ProjectB into a pip package and install it as a usual package by pip. Usefull links:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.