Search code examples
pythondirectory-structurenose

Did I organise my Python directory incorrectly?


I am trying to make a stand-alone application in Python and there are some problems related to imports and the project's directory structure that I do not how to solve.

This is how the project is structured:

root/
  app/
    __init__.py 
    main.py
    foo.py     
  tests/
    __init__.py
    main_tests.py
    foo_tests.py

These are the two conflicting requirements which I don't know how to solve:

  • The tests are written using the Nose framework. When I run nosetests from the root directory, it requires all imports to be relative to the app package.

    # app/main.py
    import app.foo  # `import foo` will not work
    
  • On the other hand, if I want to run the application from root (with a command like python app/main.py), another problem occurs. It will rightly complain that it cannot find the app package.

How can I fix these problems? Is there anything I need to change in how I organized my project?


Solution

  • You should have a setup.py; in the setup.py you should have:

    setup(
        ...
        scripts = ['bin/run_my_app']
        ...
    )
    

    and bin/run_my_app then a script with content:

    #!/usr/bin/env python
    
    from app.main import main
    main()
    

    Now when you run python setup.py develop or python setup.py install, the setuptools/distribute will install the command line script run_my_app into your path. The python setup.py develop makes it possible to not need to reinstall the package to virtualenv after each change to the source code; you need to rerun setup.py develop only after changes to the setup.py itself, or any of the possible C language extension modules in your package.

    Alternatively run your main module with

    python -m app.main
    

    Especially do not try to run an application from within the package with python app/main, as it never was supposed to work like that.


    For developing the code, you'd have a virtualenv, then you can use python setup.py develop to link the code into the virtualenv; a special link is installed into the site-packages that points to the source code of your application, thus you can develop it in place, but it behaves as if it was installed into the site-packages.