12

I'm new to Python and i have looked around on how to import my custom modules from a directory/ sub directories. Such as this and this.

This is my structure,

index.py
__init__.py
modules/
  hello.py
  HelloWorld.py
  moduletest.py

index.py,

# IMPORTS MODULES
import hello
import HelloWorld
import moduletest

# This is our application object. It could have any name,
# except when using mod_wsgi where it must be "application"
def application(environ, start_response):

    # build the response body possibly using the environ dictionary
    response_body = 'The request method was %s' % environ['REQUEST_METHOD']

    # HTTP response code and message
    status = '200 OK'

    # These are HTTP headers expected by the client.
    # They must be wrapped as a list of tupled pairs:
    # [(Header name, Header value)].
    response_headers = [('Content-Type', 'text/plain'),
                       ('Content-Length', str(len(response_body)))]

    # Send them to the server using the supplied function
    start_response(status, response_headers)

    # Return the response body.
    # Notice it is wrapped in a list although it could be any iterable.
    return [response_body]

init.py,

from modules import moduletest
from modules import hello
from modules import HelloWorld

modules/hello.py,

def hello():
    return 'Hello World from hello.py!'

modules/HelloWorld.py,

# define a class
class HelloWorld:
    def __init__(self):
        self.message = 'Hello World from HelloWorld.py!'

    def sayHello(self):
        return self.message

modules/moduletest.py,

# Define some variables:
numberone = 1
ageofqueen = 78

# define some functions
def printhello():
    print "hello"

def timesfour(input):
    print input * 4

# define a class
class Piano:
    def __init__(self):
        self.type = raw_input("What type of piano? ")
        self.height = raw_input("What height (in feet)? ")
        self.price = raw_input("How much did it cost? ")
        self.age = raw_input("How old is it (in years)? ")

    def printdetails(self):
        print "This piano is a/an " + self.height + " foot",
        print self.type, "piano, " + self.age, "years old and costing\
        " + self.price + " dollars."

But through the Apache WSGI, I get this error,

[wsgi:error] [pid 5840:tid 828] [client 127.0.0.1:54621] import hello [wsgi:error] [pid 5840:tid 828] [client 127.0.0.1:54621] ImportError: No module named hello

Any idea what have I done wrong?

EDIT:

index.py
__init__.py
modules/
  hello.py
  HelloWorld.py
  moduletest.py
  User/
    Users.py
Community
  • 1
  • 1
Run
  • 54,938
  • 169
  • 450
  • 748

4 Answers4

7

You should have an __init__.py file in the modules/ directory to tell Python that modules is a package. It can be an empty file.

If you like, you can put this into that __init__.pyto simplify importing your package's modules:

__all__ = ['hello', 'HelloWorld', 'moduletest']

From Importing * From a Package

Now what happens when the user writes from sound.effects import *? Ideally, one would hope that this somehow goes out to the filesystem, finds which submodules are present in the package, and imports them all. This could take a long time and importing sub-modules might have unwanted side-effects that should only happen when the sub-module is explicitly imported.

The only solution is for the package author to provide an explicit index of the package. The import statement uses the following convention: if a package’s __init__.py code defines a list named __all__, it is taken to be the list of module names that should be imported when from package import * is encountered. It is up to the package author to keep this list up-to-date when a new version of the package is released. Package authors may also decide not to support it, if they don’t see a use for importing * from their package.

PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
  • what should i put in that `modules/__init__.py`? – Run Aug 18 '15 at 07:28
  • @teelou: You don't _need_ to put anything. As I said, it can be an empty file. But you can put stuff in it that makes it easier to import your packages modules. I'll add some more info to my answer in a couple of minutes. – PM 2Ring Aug 18 '15 at 07:33
  • @teelou: FWIW, [here's an example](http://stackoverflow.com/a/26623508/4014959) I wrote last year of a slightly more complicated package structure. – PM 2Ring Aug 18 '15 at 07:45
  • @PM2Ring what about sub directories in `modules/` - how can I import them? – Run Aug 18 '15 at 08:02
  • 1
    @teelou: I've just seen your edit. You'll also need an `__init__.py` in `modules/User/`. Please take a look at my code that I linked to in my previous comment, since its structure is similar to the structure of your project. – PM 2Ring Aug 18 '15 at 08:22
  • @PM2Ring thanks. The crucial thing to do is what (@)plaes pointed out actually. I need to set the path to the modules.... – Run Aug 18 '15 at 08:25
  • 1
    @teelou: Sure. The top directory of your package needs to be in your Python path. So if it's not already in your normal Python path then you'll need to add it explicitly. But you don't need to worry about adding your package's sub-directories to the Python path - the `__init__.py` stuff will let Python know how to find them, once its found the top directory (from the path info) and realises that it's a package (from the `__init__.py` in that top directory). – PM 2Ring Aug 18 '15 at 08:30
3

You need to set the path to your application in the .wsgi file, which in your case it seems to be index.py:

import sys

path = '/full/path/to/app'
if path not in sys.path:
   sys.path.insert(0, path)
plaes
  • 31,788
  • 11
  • 91
  • 89
  • This actually solved the problem in my own case. There may be a better way to get the path though: `os.path.split(__file__)[0]` – orblivion Mar 18 '17 at 23:52
  • 1
    That said, it may be better to just pass the python path to wsgi. `--python-path /full/path/to/app`. – orblivion Mar 18 '17 at 23:56
2

You could also fix this in your apache virtualhost config:

WSGIDaemonProcess example home=/path/to/mysite.com python-path=/path/to/mysite.com

See http://blog.dscpl.com.au/2014/09/python-module-search-path-and-modwsgi.html for more info.

robkorv
  • 549
  • 7
  • 5
  • `WSGIProcessGroup example` (with the same group name) in the `` section was required when I tried this. – Bob Stein May 30 '19 at 18:01
0

In your code hello.py only contains a method, if you wrapped it in a class that would be seen as a module.

Setherith
  • 329
  • 2
  • 10