파이썬 웹 표준 라이브러리
파이썬 웹프로그래밍(한빛출판사) 책의 내용을 정리한 것입니다.
웹 클라이언트 라이브러리
urlparse 모듈
URL 의 분해, 조립, 변경 등 을 처리하는 함수
from urlparse import urlparse
result = urlparse("http://www.python.org:80/guido/python.html;philosophy?overall=3\n10")
urllib2 모듈
urlopen 함수
주어진 URL 에서 데이터를 가져오는 기본 기능 제공하며, 형식은 다음과 같다.
urlopen(url, data=None, [timeout])
간단한 요청은 다음과 같이 가능하다.
from urllib2 import urlopen
data = "query=python"
f = urlopen("http://www.example.com', data)
print f.read(300)
다음과 같이 Request 클래스를 활용하여 헤더를 지정할 수도 있다.
import urllib2
req = urllib2.Request("http://www.example.com")
req.add_header("Content-Type", "text/plain")
req.add_data("query=python")
f = urllib2.urlopen(req)
print f.read(300)
인증 데이터나 쿠키 데이터를 추가하여 요청을 보낼 수 있는데, 이를 위해서는 각 기능에 맞는 핸들러를 정의하고, 그 핸들러를 build_opener()
함수로 오프너를 등록하고, install_opener()
함수를 이용하여 디폴트 오프너로 설정하면 된다.
다음은 HttpBasicAuthHandler
클래스를 이용하여 인증데이터를 보내는 예이다.
import urllib2
auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password(realm='PDQ Application',
url='http://mahler:8092/site-updates.py',
user='klem',
passwd='kadidd!ehopper')
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
u = urllib2.urlopen("http://www.exmaple.com/login.html")
HTTPCookieProcessor 클래스를 사용하여 쿠키를 함께 보낼 수도 있다.
import urllib2
cookie_handler = urllib2.HTTPCookieProcessor()
opener = urllib2.build_opener(cookie_handler)
urllib2.install_opener(opener)
u = urllib2.urlopen('http://www.example.com/login.html')
프록시 서버를 통해 http 요청을 보내기 위해서는 ProxyHandler
및 ProxyBasicAuthHandler
클래스를 사용할 수 있다.
import urllib2
proxy_handler = urllib2.ProxyHandler({'http': 'http://www.example.com:3128/'})
proxy_auth_handler = urllib2.ProxyBasicAuthHandler()
proxy_auth_handler.add_password('realm', 'host', 'username', 'password')
opener = urllib2.build_opener(proxy_handler, proxy_auth_handler)
urllib2.install_opener(opener)
u = opener.open('http://www.example.com/login.html')
urllib2 모듈 예제
HTMLParser 클래스를 상속 받아 html 에서 img 태그만을 추출하여 정보를 출력하는 예제이다.
from urllib2 import urlopen
from HTMLParser import HTMLParser
class ImageParser(HTMLParser):
def handle_starttag(self, tag, attrs):
if tag != 'img':
return
if not hasattr(self, 'result'):
self.result = []
for name, value in attrs:
if name == 'src':
self.result.append(value)
def parseImage(data):
parser = ImageParser()
parser.feed(data)
dataSet = set(x for x in parser.result)
print '\n'.join(sorted(dataSet))
def main():
url = 'http://www.google.co.kr'
f = urlopen(url)
charset = f.info().getparam('charset')
data = f.read().decode(charset)
f.close()
print "\n>>>>>>>>>> Fetch Images from", url
parseImage(data)
if __name__ == '__main__':
main()
결과는 다음과 같다.
httplib 모듈
HTTP 프로토콜 요청에 대한 저수준의 더 세밀한 기능이 필요할 때 사용할 수 있다.
- httplib 모듈 사용 순서
- 연결 객체 생성
- 요청 전송
- request(method, url, body, headers) 형식
- 응답 객체 생성
- 응답 데이터 읽음
- 연결 닫음
GET 방식 요청의 경우는 다음과 같이 구현할 수 있다.
import httplib
// 연결 객체 생성
conn = httplib.HTTPConnection("www.example.com")
// 요청 전송
conn.request("GET", '/index.html')
// 응답 객체 생성
r1 = conn.getresponse()
// 응답 데이터 읽음
data1 = r1.read()
// 연결 닫음
conn.close()
하나의 연결 객체를 이용하여 여러 번의 request 를 하기 위해선 이 전의 request 에 대한 응답을 모두 읽어야 가능하다.
POST 메소드로 요청은 아래와 같은 코드로 구현할 수 있다.
import httplib, urllib
params = urllib.urlencode({'@number': 12524, '@type': 'issue', '@action': 'show'})
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
conn = httplib.HTTPConnection("bugs.python.org")
conn.request("POST", "", params, headers)
response = conn.getresponse()
data = response.read()
conn.close()
다음은 PUT 메소드로 요청을 보내는 예이다.
import httplib
body = "*****filecontents*****"
conn = httplib.HTTPConnection("localhost", 8888)
conn.request("PUT", "/file", body)
response = conn.getresponse()
웹 서버 라이브러리
웹 서버를 만드는 가장 기본적인 방법
- BaseHTTPServer 모듈을 import 한다.
- BaseHTTPRequestHandler를 상속받아 원하는 로직으로 핸들러 클래스를 정의한다.
- 서버의 ip, port 및 핸들러 클래스를 인자로 하여 HTTPServer 객체를 생성한다.
- HTTPServer 객체의 serve_forever() 메소드를 호출한다.
BaseHTTPServer 모듈
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.wfile.write("Hello World")
if __name__ == '__main__':
server = HTTPServer(('', 8888), MyHandler)
print 'Started WebServer on port 8888...'
print 'Press ^C to quit WebServer'
server.serve_forever()
SimpleHTTPServer 모듈
간단한 핸들러(SimpleHTTPRequestHandler)가 미리 구현되어 있어 필요할 때 즉시 웹 서버를 실행할 수 있다.
SimpleHTTPRequestHandler 는 do_GET()
, do_HEAD()
메소드가 정의되어 있어서 GET 및 HEAD 방식을 처리할 수 있다.
$ python -m SimpleHTTPServer 8888
CGIHTTPServer 모듈
CGIHTTPServer 모듈에는 CGIHTTPRequestHandler 가 미리 정의되어 있고, 이는 do_POST()
메소드가 정의되어 있어 POST 방식을 처리할 수 있다. 또한, SimpleHTTPRequestHandler 를 상속받고 있어서 GET, HEAD 방식 역시 처리 가능하다.
xxxHTTPServer 모듈간의 관계
이 한 장의 그림으로 모든걸 설명할 수 있음.
CGI/WSGI 라이브러리
WSGI(Web Server Gateway Interface): 웹 서버와 웹 애플리케이션을 연결해주는 규격
웹 프레임워크와 아파치와 같은 웹 서버와의 연동을 위해 사용.
CGI 관련 모듈
웹 서버와 웹 어플리케이션 간의 데이터를 주고 받기 위한 규격
- CGIHTTPServer 모듈
- cgi 모듈: http 요청에 포함된 파라미터를 처리하기 위한 FieldStorage 클래스를 정의
- cgitb 모듈: CGI 어플리케이션 실행 중 오류 발생 시 관련 정보를 브라우저에 표시
WSGI 개요
웹 서버와 웹 어플리케이션의 연동을 위해 웹 프레임워크가 사용하는 규격.
WSGI 서버의 어플리케이션 처리 과정
- Request (@웹 서버)
- Request의 URL 분석 (@웹 서버)
- WSGIScriptAlias 에 정의된 URL 이면, WSGI 서버에 처리 위임 (@웹 서버)
- 파라미터 전달
- WSGIScriptAlias 에 정의된 wsgi.py 실행 (@WSGI 서버)
- application(eviron, start_response) 함수 호출 (@WSGI 서버)
- call
- environ 환경변수 처리 (@application)
- 뷰 처리, HTTPRequest 객체 생성 (@application)
- start_response() 함수 호출 (@application)
- return HTTPResponse (@application)
- return
- 표준 출력에 결과 출력 (@WSGI 서버)
- 처리 결과
- Response (@웹 서버)
wsgiref.simple_server 모듈
def my_app(environ, start_response):
status = "200 OK"
headers = [('Content-Type', 'text/plain')]
start_response(status, headers)
return ["This is a sample WSGI Application."]
if __name__ == '__main__':
from wsgiref.simple_server import make_server
print "Started WSGI Server on port 8888..."
server = make_server('', 8888, my_app)
server.serve_forever()
위 코드는 wsgiref.simple_server
모듈을 이용한 간단한 WSGI 서버를 만드는 예이다.
- 예제에서 보듯
make_server()
를 호출할 때my_app()
과 같은 호출 가능한 함수나 메소드를 인자로 넘겨주어야 한다. 이는 어플리케이션 프로그램과 웹 서버 프로그램을 독립적으로 작성할 수 있게 해주는 WSGI 규격의 중요한 원칙에 해당한다. my_app()
함수는 WSGI 규격을 준수하는 어플리케이션 코드이다.