1

I have made several Python packages, and I've always struggled to get imports to work. My normal project structure (as given in the Python packaging user guide) is as below:

packageName/
    src/
        packageName/
            __init__.py
            file1.py
            file2.py
        tests/
            test_file1.py
            test_file2.py
            testData/
                data_for_tests.py

At the moment, when I want to use a function from file2.py in file1.py, I do from .file2 import functionName, but this seems very clunky and inelegant, and removes a lot of the benefits of abstracting things away behind files. I've also read lots of documentation saying that these relative imports are considered harmful.

I've tried just using import packageName.file2, but when I run pytest it tells me that no such package exists. The only workaround I can think of is setting up a script to build it into a wheel and installing it locally first, but that doesn't seem particularly elegant. For reference, when I run pytest, I do it by running python3 -m pytest from the package root directory.

In addition, when I want a function (say from file1) to be usable as packageName.function, I put from file1 import function into the init file. This seems alright, but with all of this other stuff, I'm wondering if that's the right way to do it.

I work with a lot of engineers who use Python, but none of them are making packages to go on pip, and this seemed like the best place to come for an answer.


On the advice of Blue Robin, I tried just using from packageName import file2, which worked on one file, but it didn't work when using other files (although I'm sure it's not a circular dependency issue). As a more concrete example, here is the project I'm currently working on:

countach/
    src/
        countach/
            __init__.py
           fileops.py     | (no imports)
           fixed.py       | (no imports)
           processing.py  | (imports fileops and types)
           types.py       | (imports fixed)

I replaced the from .fileops import _function to a from countach import fileops, and it worked (removing the underscore from the given function). I then tried with other imports, and they didn't work, giving the error ImportError: cannot import name 'types' from 'countach' (or the same type of error for fixed). Googling these errors suggested that they normally occur in circular dependencies, but that can't be the case since fixed doesn't import anything. I even tried doing it from the Python 3 REPL in the same directory, and it gave the same error.

I absolutely appreciate that you are giving your time for free here so I'm not expecting anyone to pore over anything, but any help would really be appreciated.

The code is available on my project's GitHub repository in tag v0.1.0N, but there is a further update. It turns out what was causing a lot of the problems is that I had a previous version of the package already installed via pip, so that was causing the ImportErrors to appear. I uninstalled the previous version, and now a different error has started to appear:

== types.py ==
from countach import fileops, types

Which gives the error:

ModuleNotFoundError: No module named 'countach'

I also tried replacing the from-style imports with a direct import fileops and import types, but they also give corresponding ModuleNotFoundErrors. So I guess my question has changed a little into: with the directory structure as given above, how do I import other files from the same package? I can find lots of resources for importing from other directories, but the several files I have here make a lot more sense together than apart.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
hrjkknox
  • 11
  • 3

1 Answers1

0

How to import functions, classes, and other Python files from a directory

from directory import file  # 'file' is the .py file name within the directory
from file import class  # You can replace class with any function or class in the py file

What's the ImportError: cannot import name 'types' from 'countach'?

  1. It's probably not a circular import error, but if it is, you can find more about it here
  2. It may be a misspelling issue
  3. The structure that you try to import with may be wrong.

For example: from dir import file

File structure:
dir-
-- file1
dir2-
--file

As you can see, file is in dir2 instead of dir.

I believe it is the second issue, but I don't have enough information.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Blue Robin
  • 847
  • 2
  • 11
  • 31
  • Thank you for your response. After trying it on a different machine by chance, I got a different error, and found that my problem at the time was due to having a previous version of the package installed already. I'm now getting a different error and updated it in my post if you're willing to take another look, but you've already been so helpful and given a fair amount of time. Thanks for the input. – hrjkknox Feb 28 '23 at 17:41
  • @hrjkknox I believe this is because you don't have the module installed. Try reinstalling it with pip. If that's not the case, as you may have stated before, see [here](https://stackoverflow.com/q/54598292/15982771) – Blue Robin Feb 28 '23 at 20:18
  • so just to confirm, in order to run my unit tests, I need to build and install the package? – hrjkknox Mar 02 '23 at 14:38
  • @hrjkknox If the thing you're importing needs to be installed that way, then yes. Else, see the link that I liked. This could be a simple typo or trying to access a file that doesn't exist. – Blue Robin Mar 02 '23 at 14:42