0

I read a lot of answers related to the question I am asking, but still I do not understand how to make possible this thing I am trying. So let's go to the point. I will report a simplified version of my application.

Suppose I have a main folder called project and inside it a src main package containing three subpackages:

  • clustering (containing a file: clustering.py)
  • parser (containing a file: parser.py)
  • support_class (containing a file: myClass.py)

In each folder, except for the project one, there is a __init__.py

Now, the python scripts contained in the clustering and parser package should use both the myclass.py contained in support_class.

I tried relative imports, but they do not works because I would like to run the scripts contained in the clustering and parser package directly and I do not want to use the -m option.

Es. python parser.py [arguments]

Example of relative import I used is:

from ..supportClass import myClass

I tried to add the package path to the sys.path but something is not working because it still tells me that it can't find the module.

Es.

sys.path.insert(0, "~/project/src") 
from support_class import myClass.py 

Can anyone suggest the best way to do this in python 2.7? If I could avoid the sys.path option it would be great because I do not like this solution that much.

Thanks in advance.

al27091
  • 111
  • 5
  • Could you tell us how you tried to use a relative path? – Gormador Nov 17 '16 at 17:29
  • I tried, for example in parser.py, to do something like: from ..support_class import myClass.py – al27091 Nov 17 '16 at 17:37
  • Are you running `parser.py` directly from its subfolder or are you importing it from your toplevel folder? EDIT: My bad, reading your question again, you already provided that information. – Gormador Nov 17 '16 at 17:44
  • I am running parser.py from the parser folder and trying to import myClass.py from parser.py EDIT: no worries :) – al27091 Nov 17 '16 at 17:47
  • Packages weren't designed to allow the running of subpackage modules nested inside them as main. To get the `sys.path.insert(0, "~/project/src")` to work, try using [`os.path.expanduser()`](https://docs.python.org/2/library/os.path.html?highlight=expanduser#os.path.expanduser) on the second argument before passing it to the `insert()` method. – martineau Nov 17 '16 at 18:17
  • @al27091 This was in fact a duplicate of an answered question... Tricky to formulate though :-) See my answer for more details! – Gormador Nov 17 '16 at 18:30

3 Answers3

1

Let's start from your project's folder architecture:

MyProject/
└── src
    ├── clustering
    │   ├── __init__.py
    │   └── clustering.py
    ├── parser
    │   ├── __init__.py
    │   └── parser.py
    ├── support_class
    │   ├── __init__.py
    │   └── support.py
    └── main.py  

If I'm not mistaken, your issue is that you want to import support.py from within parser.py and clustering.py and being able to run those two independently if needed. Two words for you:

Conditional imports

(And one more, after finding a real other solution ;): PYTHONPATH)

With the assumption that your scripts have a if __name__ == "__main__": section to run your tests, you can simply have the following as their imports:

clustering.py & parser.py:

if __name__ == "__main__":
    import sys
    import os

    PACKAGE_PARENT = '..'
    SCRIPT_DIR = os.path.dirname(os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__))))
    sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))

    from support_class.support import Support
else:
    from support_class.support  import Support

main.py:

from support_class.support  import Support

Then, python clustering.py and python parser.py to your heart's content!

Which makes this a duplicate of https://stackoverflow.com/a/16985066/3425488

Community
  • 1
  • 1
Gormador
  • 380
  • 2
  • 15
0

First, you have to create an __init __.py (two = "_", before and after, no spaces) file inside the directory where you have your actual package.

Second, you want to simply call your package from the python script where you are import to.

e.g.:

my_script.py #your script where you want to include/import your package

  1. my_clustering_dir # directory containing files for package
  2. my_clustering.py # file should be inside my_clustering_dir
  3. "__init __".py # make sure this file is inside my_clustering_dir only (it can be empty)

Now, you can go to my_script.py. Then, you can add the following:

 from my_clustering_dir import my_clustering  #no extension (.py) needed
itsmrbeltre
  • 412
  • 7
  • 18
0

When you call a python script like this

python parser.py

That module is loaded as __main__, not parser.parser. It won't be loaded as part of any package, so it can't do relative imports. The correct way to do this is to create a separate script that is only used as the main script and not use any of your module scripts as main scripts. For example, create a script like this

main.py

from parser import parser
parser.main()

Then you can run python /path/to/main.py and it will work.

Also, a note on your package layout. In your example, parser and clustering and support_class aren't subpackages, they are top-level packages. Typically, if you have a package named project and you're using a src directory, your layout would look like this:

/project
  setup.py
  /src
    /project
      __init__.py
      /clustering
        __init__.py
      /parser
        ..

Alternatively, if you're building an actual python package with a setup.py script, you can use the console_scripts entry point in setuptools to generate the script automatically.

setup(
    ...
    entry_points = {
        'console_scripts': ['myparser=project.parser:main'],
    }
    ...
)
Brendan Abel
  • 35,343
  • 14
  • 88
  • 118