python 아파치 + wsgi :: Python일반[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

Python일반
[1]
등록일:2015-05-28 13:45:27 (0%)
작성자:
제목:python 아파치 + wsgi

보다가 짜증나기 십상이니 보지 마시길...

 

WSGI(Web Server Gateway Interface)는 python언어에서 웹서버와 웹어플/웹프레임워크 사이를 이어주는 인터페이스다. - PEP333(2010년) 참고.

web server 아파치에서 파이썬으로 웹구현을 하는데는 mod_python모듈도 있지만 더 나은mod_wsgi를 써보자.

wsgi를 지원하는 pytthon framework로는 CherryPy, Django, Tornado, web.py, web2py, Flask, Pylons, Pyramid, BlueBream,.....

하도 많으니 고르기도 어렵지만 framework을 꼭 써야되는가?  안쓰고는 베길 재간이 없다. 

예전에 Flask를 써서 웹으로 원격 GPIO제어를 했었는데 다시 하려니 백지상태로 되버렸다.ㅜ.

 

자바나 PHP등 웹에 좋은 언어가 많은데 궂이 python으로 하려고 하냐고 묻는다면, 먼저 파이썬으로 만들어진 좋은 어플이나 라이브러리가 있는데 웹에서 처리하고 싶을때 파이슨으로 처리하는것이 가장 좋기 때문이다.

 

웹서버는 아파치를 쓸거고 파이썬은 3.X를 쓰려고 한다. 파이썬이 2.X버전과 3.X버전이 호환이 안되 버전에 따라 되는지 않되는지 잘 살펴야한다. 라이브러리가 3.X로 만들어 졌는데 framework이 2.X밖에 지원안된다면 내가 라이브러리까지 다 손봐야 한다.

 

The following packages have unmet dependencies:

 libapache2-mod-wsgi-py3 : Conflicts: libapache2-mod-wsgi but 3.3-4+deb7u1 is to be installed

E: Unable to correct problems, you have held broken packages.

==> python2.x 와 python3.x는 같이 쓸수 없다는것으로 보인다. 프레임웤이 2.x버전으로 만들어진것과 3.x버전으로 만들어진것을 살펴봐야겟다. 

Django(장고)가 요즘 점유율이 높은것같다.
pi@raspberrypi /etc/apache2 $ sudo apt-get install django*
....
0 upgraded, 179 newly installed, 0 to remove and 10 not upgraded.
허걱!! 179개나!!
그리고 2.x만 지원한듯 보인다. 3.x가 안보임. 게다가 깔야야될 모듈이 너무 어지럽게 널려있어 좀 불안하다.

CherryPy를 찾아보니
A Minimalist Python Web Framework. 
Runs on Python 2.5+, 3.1+, PyPy, Jython and Android. 
A flexible plugin system. 
CherryPy is a pythonic, object-oriented web framework.

이런 말들이 보인다. .. 성능은 모르겟지만 맘에드는 말이 많다.
 

pi@raspberrypi /etc/apache2 $ sudo apt-cache search cherrypy
python-cherrypy - Python web development framework

python-cherrypy3 - Python web development framework - version 3
python-sponge - Sponge is a web framework built on top of CherryPy and Genshi

모듈갯수도 작아서 괜찮고,... 깔자

Setting up python-cherrypy3 (3.2.2-2) ...

pi@raspberrypi /etc/apache2 $ python3
Python 3.2.3 (default, Mar  1 2013, 11:53:50)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cherrypy
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named cherrypi

pi@raspberrypi ~ $ python
Python 2.7.3 (default, Mar 18 2014, 05:13:23)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cherrypy
>>>

pi@raspberrypi ~ $ sudo apt-get install cherrypy*
Reading package lists... Done
Building dependency tree
Reading state information... Done
Note, selecting 'python2.4-cherrypy' for regex 'cherrypy*'
Note, selecting 'python-cherrypy3' for regex 'cherrypy*'
Note, selecting 'python2.3-cherrypy' for regex 'cherrypy*'
Note, selecting 'python2.6-cherrypy3' for regex 'cherrypy*'
Note, selecting 'python2.7-cherrypy3' for regex 'cherrypy*'
Note, selecting 'python2.3-cherrypy2.1' for regex 'cherrypy*'
Note, selecting 'python2.6-cherrypy' for regex 'cherrypy*'
Note, selecting 'python2.5-cherrypy' for regex 'cherrypy*'
Note, selecting 'python2.4-cherrypy2.1' for regex 'cherrypy*'
Note, selecting 'python-cherrypy' for regex 'cherrypy*'
Note, selecting 'python-cherrypy' instead of 'python2.4-cherrypy'
Note, selecting 'python-cherrypy' instead of 'python2.5-cherrypy'
Note, selecting 'python-cherrypy' instead of 'python2.6-cherrypy'
Note, selecting 'python-cherrypy3' instead of 'python2.6-cherrypy3'
Note, selecting 'python-cherrypy3' instead of 'python2.7-cherrypy3'
python-cherrypy3 is already the newest version.
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 python-cherrypy3 : Conflicts: python-cherrypy but 2.3.0-3 is to be installed
                    Conflicts: python2.4-cherrypy
E: Unable to correct problems, you have held broken packages.

이름보면 python3지원하는것 같은데 python3에선 모듈이 안올라온다. 

pi@raspberrypi ~ $ cat www/t2.py
import cherrypy

class HelloWorld(object):
        @cherrypy.expose
        def index(seld):
                return "Hello World"

if __name__ == '__main__':
        cherrypy.quickstart(HelloWorld())


pi@raspberrypi ~/www $ python t2.py
[22/Jun/2014:21:30:34] ENGINE Listening for SIGHUP.
[22/Jun/2014:21:30:34] ENGINE Listening for SIGTERM.
[22/Jun/2014:21:30:34] ENGINE Listening for SIGUSR1.
[22/Jun/2014:21:30:34] ENGINE Bus STARTING
CherryPy Checker:
The Application mounted at '' has an empty config.

[22/Jun/2014:21:30:34] ENGINE Started monitor thread '_TimeoutMonitor'.
[22/Jun/2014:21:30:34] ENGINE Started monitor thread 'Autoreloader'.
[22/Jun/2014:21:30:34] ENGINE Serving on 127.0.0.1:8080
[22/Jun/2014:21:30:34] ENGINE Bus STARTED

^C[22/Jun/2014:21:35:34] ENGINE Keyboard Interrupt: shutting down bus
[22/Jun/2014:21:35:34] ENGINE Bus STOPPING
[22/Jun/2014:21:35:34] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('127.0.0.1', 8080)) shut down
[22/Jun/2014:21:35:34] ENGINE Stopped thread 'Autoreloader'.
[22/Jun/2014:21:35:34] ENGINE Stopped thread '_TimeoutMonitor'.
[22/Jun/2014:21:35:34] ENGINE Bus STOPPED
[22/Jun/2014:21:35:34] ENGINE Bus EXITING
[22/Jun/2014:21:35:34] ENGINE Bus EXITED
[22/Jun/2014:21:35:34] ENGINE Waiting for child threads to terminate...

---> wsgi프레임워크로는 좀 그렇고 아주 가벼운 파이선 웹서버로는 쓸만 하다. 
다 지우고 다시 장고로


sudo apt-get install python-pip
sudo pip install --upgrade pip
sudo apt-get install python-django
Suggested packages: python-psycopg python-mysqldb python-flup python-sqlite python-yaml geoip-database-contrib

pi@raspberrypi ~ $         locate wsgi.py
/home/pi/dev/mod_wsgi-4.2.4/src/server/management/commands/runmodwsgi.py
/usr/lib/python2.6/dist-packages/django/conf/project_template/project_name/wsgi.py
/usr/lib/python2.6/dist-packages/django/conf/project_template/project_name/wsgi.pyc
/usr/lib/python2.6/dist-packages/django/core/handlers/wsgi.py
/usr/lib/python2.6/dist-packages/django/core/handlers/wsgi.pyc
/usr/lib/python2.6/dist-packages/django/core/wsgi.py
/usr/lib/python2.6/dist-packages/django/core/wsgi.pyc
/usr/lib/python2.7/dist-packages/django/conf/project_template/project_name/wsgi.py
/usr/lib/python2.7/dist-packages/django/conf/project_template/project_name/wsgi.pyc
/usr/lib/python2.7/dist-packages/django/core/handlers/wsgi.py
/usr/lib/python2.7/dist-packages/django/core/handlers/wsgi.pyc
/usr/lib/python2.7/dist-packages/django/core/wsgi.py
/usr/lib/python2.7/dist-packages/django/core/wsgi.pyc
/usr/share/pyshared/django/conf/project_template/project_name/wsgi.py
/usr/share/pyshared/django/core/handlers/wsgi.py
/usr/share/pyshared/django/core/wsgi.py

확실히 설치된 장고가 python3.x는 지원하지 않는다.
양이 어마어마한데 wsgi.py파일만 찾아보니 위에처럼 나오는데 이름은 같아도 내용이 다르다. 

pi@raspberrypi ~ $ cat /usr/lib/python2.7/dist-packages/django/core/wsgi.py
from django.core.handlers.wsgi import WSGIHandler

def get_wsgi_application():
    """
    The public interface to Django's WSGI support. Should return a WSGI
    callable.

    Allows us to avoid making django.core.handlers.WSGIHandler public API, in
    case the internal WSGI implementation changes or moves in the future.

    """
    return WSGIHandler()

~~
pi@raspberrypi ~ $ cat /usr/share/pyshared/django/core/handlers/wsgi.py
import sys
from threading import Lock
try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO

from django import http
from django.core import signals
from django.core.handlers import base
from django.core.urlresolvers import set_script_prefix
from django.utils import datastructures
from django.utils.encoding import force_unicode, iri_to_uri
from django.utils.log import getLogger

logger = getLogger('django.request')


STATUS_CODE_TEXT = {
    100: 'CONTINUE',
    101: 'SWITCHING PROTOCOLS',
    102: 'PROCESSING',
    200: 'OK',
    201: 'CREATED',
    202: 'ACCEPTED',
    203: 'NON-AUTHORITATIVE INFORMATION',
    204: 'NO CONTENT',
    205: 'RESET CONTENT',
    206: 'PARTIAL CONTENT',
    207: 'MULTI-STATUS',
    208: 'ALREADY REPORTED',
    226: 'IM USED',
    300: 'MULTIPLE CHOICES',
    301: 'MOVED PERMANENTLY',
    302: 'FOUND',
    303: 'SEE OTHER',
    304: 'NOT MODIFIED',
    305: 'USE PROXY',
    306: 'RESERVED',
    307: 'TEMPORARY REDIRECT',
    400: 'BAD REQUEST',
    401: 'UNAUTHORIZED',
    402: 'PAYMENT REQUIRED',
    403: 'FORBIDDEN',
    404: 'NOT FOUND',
    405: 'METHOD NOT ALLOWED',
    406: 'NOT ACCEPTABLE',
    407: 'PROXY AUTHENTICATION REQUIRED',
    408: 'REQUEST TIMEOUT',
    409: 'CONFLICT',
    410: 'GONE',
    411: 'LENGTH REQUIRED',
    412: 'PRECONDITION FAILED',
    413: 'REQUEST ENTITY TOO LARGE',
    414: 'REQUEST-URI TOO LONG',
    415: 'UNSUPPORTED MEDIA TYPE',
    416: 'REQUESTED RANGE NOT SATISFIABLE',
    417: 'EXPECTATION FAILED',
    422: 'UNPROCESSABLE ENTITY',
    423: 'LOCKED',
    424: 'FAILED DEPENDENCY',
    426: 'UPGRADE REQUIRED',
    500: 'INTERNAL SERVER ERROR',
    501: 'NOT IMPLEMENTED',
    502: 'BAD GATEWAY',
    503: 'SERVICE UNAVAILABLE',
    504: 'GATEWAY TIMEOUT',
    505: 'HTTP VERSION NOT SUPPORTED',
    506: 'VARIANT ALSO NEGOTIATES',
    507: 'INSUFFICIENT STORAGE',
    508: 'LOOP DETECTED',
    510: 'NOT EXTENDED',
}

class LimitedStream(object):
    '''
    LimitedStream wraps another stream in order to not allow reading from it
    past specified amount of bytes.
    '''
    def __init__(self, stream, limit, buf_size=64 * 1024 * 1024):
        self.stream = stream
        self.remaining = limit
        self.buffer = ''
        self.buf_size = buf_size

    def _read_limited(self, size=None):
        if size is None or size > self.remaining:
            size = self.remaining
        if size == 0:
            return ''
        result = self.stream.read(size)
        self.remaining -= len(result)
        return result

    def read(self, size=None):
        if size is None:
            result = self.buffer + self._read_limited()
            self.buffer = ''
        elif size < len(self.buffer):
            result = self.buffer[:size]
            self.buffer = self.buffer[size:]
        else: # size >= len(self.buffer)
            result = self.buffer + self._read_limited(size - len(self.buffer))
            self.buffer = ''
        return result

    def readline(self, size=None):
        while '\n' not in self.buffer and \
              (size is None or len(self.buffer) < size):
            if size:
                # since size is not None here, len(self.buffer) < size
                chunk = self._read_limited(size - len(self.buffer))
            else:
                chunk = self._read_limited()
            if not chunk:
                break
            self.buffer += chunk
        sio = StringIO(self.buffer)
        if size:
            line = sio.readline(size)
        else:
            line = sio.readline()
        self.buffer = sio.read()
        return line


class WSGIRequest(http.HttpRequest):
    def __init__(self, environ):
        script_name = base.get_script_name(environ)
        path_info = force_unicode(environ.get('PATH_INFO', u'/'))
        if not path_info or path_info == script_name:
            # Sometimes PATH_INFO exists, but is empty (e.g. accessing
            # the SCRIPT_NAME URL without a trailing slash). We really need to
            # operate as if they'd requested '/'. Not amazingly nice to force
            # the path like this, but should be harmless.
            #
            # (The comparison of path_info to script_name is to work around an
            # apparent bug in flup 1.0.1. See Django ticket #8490).
            path_info = u'/'
        self.environ = environ
        self.path_info = path_info
        self.path = '%s%s' % (script_name, path_info)
        self.META = environ
        self.META['PATH_INFO'] = path_info
        self.META['SCRIPT_NAME'] = script_name
        self.method = environ['REQUEST_METHOD'].upper()
        self._post_parse_error = False
        try:
            content_length = int(self.environ.get('CONTENT_LENGTH'))
        except (ValueError, TypeError):
            content_length = 0
        self._stream = LimitedStream(self.environ['wsgi.input'], content_length)
        self._read_started = False

    def get_full_path(self):
        # RFC 3986 requires query string arguments to be in the ASCII range.
        # Rather than crash if this doesn't happen, we encode defensively.
        return '%s%s' % (self.path, self.environ.get('QUERY_STRING', '') and ('?' + iri_to_uri(self.environ.get('QUERY_STRING', ''))) or '')

    def _is_secure(self):
        return 'wsgi.url_scheme' in self.environ and self.environ['wsgi.url_scheme'] == 'https'

    def _get_request(self):
        if not hasattr(self, '_request'):
            self._request = datastructures.MergeDict(self.POST, self.GET)
        return self._request

    def _get_get(self):
        if not hasattr(self, '_get'):
            # The WSGI spec says 'QUERY_STRING' may be absent.
            self._get = http.QueryDict(self.environ.get('QUERY_STRING', ''), encoding=self._encoding)
        return self._get

    def _set_get(self, get):
        self._get = get

    def _get_post(self):
        if not hasattr(self, '_post'):
            self._load_post_and_files()
        return self._post

    def _set_post(self, post):
        self._post = post

    def _get_cookies(self):
        if not hasattr(self, '_cookies'):
            self._cookies = http.parse_cookie(self.environ.get('HTTP_COOKIE', ''))
        return self._cookies

    def _set_cookies(self, cookies):
        self._cookies = cookies

    def _get_files(self):
        if not hasattr(self, '_files'):
            self._load_post_and_files()
        return self._files

    GET = property(_get_get, _set_get)
    POST = property(_get_post, _set_post)
    COOKIES = property(_get_cookies, _set_cookies)
    FILES = property(_get_files)
    REQUEST = property(_get_request)


class WSGIHandler(base.BaseHandler):
    initLock = Lock()
    request_class = WSGIRequest

    def __call__(self, environ, start_response):
        # Set up middleware if needed. We couldn't do this earlier, because
        # settings weren't available.
        if self._request_middleware is None:
            self.initLock.acquire()
            try:
                try:
                    # Check that middleware is still uninitialised.
                    if self._request_middleware is None:
                        self.load_middleware()
                except:
                    # Unload whatever middleware we got
                    self._request_middleware = None
                    raise
            finally:
                self.initLock.release()

        set_script_prefix(base.get_script_name(environ))
        signals.request_started.send(sender=self.__class__)
        try:
            try:
                request = self.request_class(environ)
            except UnicodeDecodeError:
                logger.warning('Bad Request (UnicodeDecodeError)',
                    exc_info=sys.exc_info(),
                    extra={
                        'status_code': 400,
                    }
                )
                response = http.HttpResponseBadRequest()
            else:
                response = self.get_response(request)
        finally:
            signals.request_finished.send(sender=self.__class__)

        try:
            status_text = STATUS_CODE_TEXT[response.status_code]
        except KeyError:
            status_text = 'UNKNOWN STATUS CODE'
        status = '%s %s' % (response.status_code, status_text)
        response_headers = [(str(k), str(v)) for k, v in response.items()]
        for c in response.cookies.values():
            response_headers.append(('Set-Cookie', str(c.output(header=''))))
        start_response(status, response_headers)
        return response

~~~

Forbidden

You don't have permission to access /index.py on this server.

 

pi@raspberrypi ~ $ ll /var/www
total 28
drwxr-xr-x 3 pi pi 4096 Jun 23 11:46 html
drwxr-xr-x 2 pi pi 4096 Jun 23 12:13 icon
drwxr-xr-x 2 pi pi 4096 Jun 23 12:13 image
drwxr-xr-x 2 pi pi 4096 Jun 23 12:13 jsscript
drwxr-xr-x 2 pi pi 4096 Jun 23 12:13 media
drwxr-xr-x 2 pi pi 4096 Jun 23 12:21 py
drwxr-xr-x 2 pi pi 4096 Jun 23 12:13 sound
몇개 폴더 더 만들고

pi@raspberrypi ~ $ cat /etc/apache2/sites-available/default
<VirtualHost *:80>
        ServerAdmin webmaster@localhost
#       ServerName      pi

        DocumentRoot /var/www/html

        <Directory /var/www/html>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

        JkMount /*.jsp  ajp13_worker
        JkMount /servlet/*  ajp13_worker
        JkMount /examples/*  ajp13_worker
        JkMount /docs/*  ajp13_worker
        JkMount /manager/*  ajp13_worker
        JkMount /host-manager/*  ajp13_worker

        WSGIScriptAlias / /var/www/py/django.wsgi

#WSGIDaemonProcess ericholscher processes=2 maximum-requests=500 threads=1
#WSGIProcessGroup ericholscher

        Alias   /media  /var/www/media/
        Alias   /sound  /var/www/sound/
        Alias   /image  /var/www/image/
        Alias   /icon   /var/www/icon

        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
        <Directory "/usr/lib/cgi-bin">
                AllowOverride None
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

~~~

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator, webmaster@localhost and inform them of the time the error occurred, and anything you might have done that may have caused the error.

More information about this error may be available in the server error log.

 

 

log에는 
[Mon Jun 23 14:28:29 2014] [error] [client 192.168.1.3] mod_wsgi (pid=16740): Target WSGI script '/var/www/py/django.wsgi' cannot be loaded as Python module.
[Mon Jun 23 14:28:29 2014] [error] [client 192.168.1.3] mod_wsgi (pid=16740): Exception occurred processing WSGI script '/var/www/py/django.wsgi'.
[Mon Jun 23 14:28:29 2014] [error] [client 192.168.1.3] Traceback (most recent call last):
[Mon Jun 23 14:28:29 2014] [error] [client 192.168.1.3]   File "/var/www/py/django.wsgi", line 16, in <module>
[Mon Jun 23 14:28:29 2014] [error] [client 192.168.1.3]     import django.core.handlers.wsgi
[Mon Jun 23 14:28:29 2014] [error] [client 192.168.1.3]   File "/usr/lib/python2.7/dist-packages/django/core/handlers/wsgi.py", line 131
[Mon Jun 23 14:28:29 2014] [error] [client 192.168.1.3]     path_info = force_unicode(environ.get('PATH_INFO', u'/'))
[Mon Jun 23 14:28:29 2014] [error] [client 192.168.1.3]                                                           ^
[Mon Jun 23 14:28:29 2014] [error] [client 192.168.1.3] SyntaxError: invalid syntax

이렇게 나온다. 

터미널에서 하면 모듈이 잘 올라오는데 웹에 올리면 못올라온다.
PATH나 HOME같은 환경변수 때문으로 보이는데 

pi@raspberrypi /etc/apache2 $ cat sites-available/default
<VirtualHost *:80>
        ServerAdmin webmaster@localhost
#       ServerName      pi

        DocumentRoot /var/www/html

        <Directory /var/www/html>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>

        JkMount /*.jsp  ajp13_worker
        JkMount /servlet/*  ajp13_worker
        JkMount /examples/*  ajp13_worker
        JkMount /docs/*  ajp13_worker
        JkMount /manager/*  ajp13_worker
        JkMount /host-manager/*  ajp13_worker

        WSGIScriptAlias / /var/www/py/django.wsgi

WSGIDaemonProcess ericholscher processes=2 python-path=/usr/share/pyshared/django/ maximum-requests=500 threads=1
WSGIProcessGroup ericholscher

        Alias   /media  /var/www/media/
        Alias   /sound  /var/www/sound/
        Alias   /image  /var/www/image/
        Alias   /icon   /var/www/icon

pi@raspberrypi /etc/apache2 $ cat /var/www/py/django.wsgi
import os, sys, site

'/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7'

sys.path.append('/var/www/py')
sys.path.append('/usr/lib/python2.7')
sys.path.append('/usr/lib/python2.7/plat-linux2')
sys.path.append('/usr/lib/python2.7/lib-dynload')
sys.path.append('/usr/local/lib/python2.7/dist-packages')
sys.path.append('/usr/lib/python2.7/dist-packages')
sys.path.append('/usr/lib/pymodules/python2.7')
site.addsitedir('/usr/share/pyshared')

os.environ['DJANGO_SETTINGS_MODULE'] = 'py.settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

이렇게 돼있다.

DJANGO_SETTINGS_MODULE에 대한것이 http://stackoverflow.com/questions/7479493/django-settings-module-is-undefined 여기에 잘나와있다.

pi@raspberrypi ~ $ locate django-admin.py
/usr/lib/python2.6/dist-packages/django/bin/django-admin.py
/usr/lib/python2.6/dist-packages/django/bin/django-admin.pyc
/usr/lib/python2.7/dist-packages/django/bin/django-admin.py
/usr/lib/python2.7/dist-packages/django/bin/django-admin.pyc
/usr/share/pyshared/django/bin/django-admin.py

pi@raspberrypi /var/www $ python /usr/lib/python2.7/dist-packages/django/bin/django-admin.py startproject py
Error: '/var/www/py' already exists
pi@raspberrypi /var/www $ mv py py_
pi@raspberrypi /var/www $ python /usr/lib/python2.7/dist-packages/django/bin/django-admin.py startproject py
pi@raspberrypi /var/www $ la py
total 16
drwxr-xr-x  3 pi pi 4096 Jun 23 16:13 ./
drwxr-xr-x 10 pi pi 4096 Jun 23 16:13 ../
-rwxr-xr-x  1 pi pi  245 Jun 23 16:13 manage.py*
drwxr-xr-x  2 pi pi 4096 Jun 23 16:13 py/
pi@raspberrypi /var/www $ la py/py
total 24
drwxr-xr-x 2 pi pi 4096 Jun 23 16:13 ./
drwxr-xr-x 3 pi pi 4096 Jun 23 16:13 ../
-rw-r--r-- 1 pi pi    0 Jun 23 16:13 __init__.py
-rw-r--r-- 1 pi pi 5374 Jun 23 16:13 settings.py
-rw-r--r-- 1 pi pi  544 Jun 23 16:13 urls.py
-rw-r--r-- 1 pi pi 1126 Jun 23 16:13 wsgi.py


/var/www/py/django.wsgi에 패스 추가해줬다.(굵은부분)
#! /usr/bin/python
import os, sys, site

"""
'/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7'
"""

sys.path.append('/var/www/py')
sys.path.append('/usr/lib/python2.7')
sys.path.append('/usr/lib/python2.7/plat-linux2')
sys.path.append('/usr/lib/python2.7/lib-dynload')
sys.path.append('/usr/local/lib/python2.7/dist-packages')
sys.path.append('/usr/lib/python2.7/dist-packages')
sys.path.append('/usr/lib/pymodules/python2.7')
site.addsitedir('/usr/share/pyshared')
site.addsitedir('/usr/lib/python2.7/dist-packages')

os.environ['DJANGO_SETTINGS_MODULE'] = 'py.settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

~~


짜증나게 감격스럽다.ㅋ  패스 잘못잡아줘서리... 하지만 아직도 가시덤불속

/etc/apache2/site-available/default

==>
WSGIPythonPath /var/www/html
<VirtualHost *:80>
        ServerAdmin webmaster@localhost
#       ServerName      pi

        DocumentRoot /var/www/html

        <Directory /var/www/html>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                DirectoryIndex index.html index.jsp index.php index.py
                Options +Indexes ExecCGI FollowSymLinks MultiViews
#               SetHandler wsgi-script
                allow from all
        </Directory>

        JkMount /*.jsp  ajp13_worker
        JkMount /servlet/*  ajp13_worker
        JkMount /examples/*  ajp13_worker
        JkMount /docs/*  ajp13_worker
        JkMount /manager/*  ajp13_worker
        JkMount /host-manager/*  ajp13_worker

WSGIDaemonProcess hek processes=2 python-path=/usr/lib/python2.7/dist-packages/ maximum-requests=200 threads=1
WSGIProcessGroup hek


        Alias   /media/ /var/www/media/
        Alias   /sound/ /var/www/sound/
        Alias   /image/ /var/www/image/
        Alias   /icons/ /var/www/icons/

        WSGIScriptAlias /py/ /var/www/py/django.wsgi/

        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
        <Directory "/usr/lib/cgi-bin">
                AllowOverride None
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>

        ScriptAlias     /py/    /var/www/py/
        <Directory "/var/www/py">
                AllowOverride None
                Options +Indexes ExecCGI FollowSymLinks MultiViews
                Order allow,deny
                DirectoryIndex index.html index.py
                SetHandler wsgi-script
                Allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

html, jsp, php, python
/var/www/html 아래에서 위 네가지언어 아무거나 쓸 수 있다.

아직 django가 어떻게 동작하는지 어떻게 쓰는지 감이 오지 않는다. 
지금하고 있는건 장고가 아니고 그냥 wsgi로 python을 쓰는것일뿐 장고의 프레임워크를 쓰는건 아니다.

장고 지우고 다시 python-flask설치

pi@raspberrypi /var/www $ sudo apt-get install python-flask
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  python-jinja2 python-markupsafe python-openssl python-werkzeug
Suggested packages:
  python-jinja2-doc python-openssl-doc python-openssl-dbg ipython python-genshi
  python-lxml python-memcache libjs-sphinxdoc
The following NEW packages will be installed:
  python-flask python-jinja2 python-markupsafe python-openssl python-werkzeug
0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,899 kB of archives.
After this operation, 5,854 kB of additional disk space will be used.

2년전 내용이지만 내가 알아 먹을 수 있는 반가운곳이다.

pi@raspberrypi ~/www/python $ cat wsgi_info.py
##
##   display environment variables in mod_wsgi - shows if wsgi, flask etc is working
##

from flask import Flask, request, make_response
import sys
application = Flask(__name__)

def showEnv(environ):
        version = sys.version

        o = "<table>"
        o += "<tr>"
        o += "<td>Python version</td>"
        o += "<td>"+str(version)+"</td>"
        for key in environ:
                o += "<tr>"
                o += "<td>"+str(key)+"</td>"
                o += "<td>"+str(environ[key])+"</td>"
                o += "</tr>\n"
        o += "</table>"
        return o

def WSerrorTextHTML(txt):
        err = "<p>ERROR!</p>"
        err += "<pre>"+ txt + "</pre>"
        return err

@application.route('/', methods=['POST', 'GET'])
def indexApp():
        try:
                env = request.environ
                output = 'Hello World!<hr>'

                if not env['mod_wsgi.process_group']:
                        output += 'EMBEDDED MODE<hr>'
                else:
                        output += 'DAEMON MODE<hr>'

                output += showEnv(env) + "<hr>"
                output += str(request.method) + "<hr>"
                output += str(__name__)
                return output
        except:
                import traceback
                response = make_response(WSerrorTextHTML(traceback.format_exc()))
                response.headers['Content-Type'] = 'text/html'
                return response

        return "<p>something wrong!</p>"

if __name__ == "__main__":
        application.run()





pi@raspberrypi ~/www/python $ cat demo.py
##
##  filename: demo.py
##
##  this is a wrapper for your main program, its primary purpose is to
##  manage error messages and output your HTML, XML or JSON as required
##

from flask import Flask, request, make_response
application = Flask(__name__)

import traceback
import os
import sys
CURRENTDIR = os.path.dirname(os.path.abspath(__file__))
if CURRENTDIR not in sys.path:
   sys.path.append(CURRENTDIR)

def wsErrorTextHTML(txt):
   ## displays the python error on the web page - useful for debugging
   ## but on a live system would have it save the error to a database and give the user an error number
   err = "<p>ERROR!</p>"
   err += "<pre>"+ txt + "</pre>"
   return err

@application.errorhandler(500)
def internalServerError(error):
   err = "<p>ERROR! 500</p>"
   err += "<pre>"+ str(error) + "</pre>"
   err += "<pre>"+ str(traceback.format_exc()) + "</pre>"
   return err

@application.route('/', methods=['POST', 'GET'])
def indexApp():

   try:
      ##
      ## ...your code goese here...
      ## I normally create a seperate 'core' application, in this case demoCore.py
      ##
      from demoCore import DemoCore
      demoCore = DemoCore()
      htmlData = demoCore.index(request)

      ## output your html code
      response = make_response(htmlData)
      response.headers['Content-Type'] = 'text/html'
      return response
   except:
      ## for when you get an error message
      response = make_response(wsErrorTextHTML(traceback.format_exc()))
      response.headers['Content-Type'] = 'text/html'
      return response




이제 각 언어별로 DB에 연결해 봐야겟다.

<도움>

출처 : http://blog.naver.com/gauya?Redirect=Log&logNo=220036981551
[본문링크] python 아파치 + wsgi
[1]
코멘트(이글의 트랙백 주소:/cafe/tb_receive.php?no=34441
작성자
비밀번호

 

SSISOCommunity

[이전]

Copyright byCopyright ⓒ2005, SSISO Community All Rights Reserved.