From what I see, it seems that utils
is a utility package logically separate from the code in Twitter.py
. Given this, what you want is to cause your utils
package to be on your Python search path (sys.path
) so that you can import that package as a separate entity (no relative paths). If you don't want to configure your environment to place utils
on the Python search path, you can do it in your Twitter.py
file. Here's how that looks:
import os
import sys
here = os.path.dirname(__file__)
sys.path.append(os.path.join(here, '..'))
import utils
utils.MagicEden.hello()
utils.OpenSea.hello()
utils.Tools.hello()
The first line of code computes the full path to the directory containing Twitter.py
. The second line then computes the path to the parent directory of that directory and adds that path to sys.path
, the Python search path. After doing this, import utils
will work, giving you access to that package and everything imported in that package's __init__.py
file.
I created three small files for magic_eden.py
, open_sea.py
, and tools.py
, each containing something that looks like this:
class MagicEden:
@staticmethod
def hello():
print("Hello from MagicEden!")
I can then run Twitter.py
, and I get the following result with no additional configuration:
Hello from MagicEden!
Hello from OpenSea!
Hello from Tools!
There's nothing wrong with using the above solution during early development. But you will likely at some point want to remove the code that is hacking sys.path
and instead install your module in a more official way. There's a way to do this from the start so that you never have to change code on either side when you want to install your module in the official way...
What I do in situations like this is create a setup.py
file in my package that lets me build it as an installable package. There are many docs and tutorials on the net that explain how to do this. Here's just one of them: https://python-packaging-tutorial.readthedocs.io/en/latest/setup_py.html
Once you've done this, what you can do is install your package in "development mode" (pip install -e <package file>). What this does is install the package so that your system can find it (adds it to sys.path
as a package), but installs links to the original sources rather than installing copies of them. In this mode, when you make changes to that package's source files, the changes take immediate effect in the installed module. So now you have the best of both worlds. Your package is installed in the official way such that you don't need to do anything special in the code that imports that package (no need to modify sys.path
), and yet you can still make changes directly to the sources for that package and not have to keep reinstalling the package to see those changes take affect.
When you're done messing with a package in this way, you can reinstall it in the regular mode (pip install <package file>
) and isolate changes to the sources for that package from uses of the package elsewhere on your system. At this point, you need to rebuild and reinstall the package to see any changes you've made to its sources.