Python에서 정적 파일을 제공하는 가장 빠른 방법은 무엇입니까? Nginx의 정적 파일 제공과 동등하거나 가까운 것을 찾고 있습니다.Python 빠른 정적 파일 제공
저는 SimpleHTTPServer에 대해 알고 있지만 여러 파일을 효율적이고 안정적으로 처리 할 수 있는지 여부는 확신 할 수 없습니다.
또한 lib/framework가 경량 인 한 일종의 lib/framework의 일부가 될 필요는 없습니다.
Python에서 정적 파일을 제공하는 가장 빠른 방법은 무엇입니까? Nginx의 정적 파일 제공과 동등하거나 가까운 것을 찾고 있습니다.Python 빠른 정적 파일 제공
저는 SimpleHTTPServer에 대해 알고 있지만 여러 파일을 효율적이고 안정적으로 처리 할 수 있는지 여부는 확신 할 수 없습니다.
또한 lib/framework가 경량 인 한 일종의 lib/framework의 일부가 될 필요는 없습니다.
제 3 자 HTTP 서버를 사용하여 정적 파일을 제공하는 것이 좋습니다.
nginx와 같은 서버는 빠른 작업 언어로 병렬화되고 작성된 작업에 집중적으로 사용됩니다.
파이썬이 하나의 프로세서에 연결되어 있고 해석됩니다.
>가 해석됩니다. Doss't 문제가 많습니다. 파일 서비스는 IOBound입니다. –
'파이썬이 하나의 프로세서에 묶여있다 ' 결코 하나의 프로세서에 묶여 있지 않다. 스레딩에서 GIL 만 잠급니다. Python mutliprocessing 표준 라이브러리와 많은 병렬 처리 타사 라이브러리가 스레딩보다 우수하며 모든 것이 다중 프로세서에서 작동합니다. –
원본 SimpleHTTPServer 파이썬 표준 라이브러리에서 "은 여러 파일을 효율적이고 안정적으로 처리합니다. ". 예를 들어, 하나의 파일을 다운로드하는 경우 SimpleHTTPServer.py
이 인 단순 싱글 스레드 HTTP 서버은 동시에 하나만 연결하면을 지원할 수 있기 때문에 다른 HTTP 액세스가 있어야합니다. 다행히
은 또한 파이썬 표준 라이브러리에서 SocketServer.ForkingMixIn 및 SocketServer.ThreadingMixIn 래핑 할 수 SimpleHTTPServer.py
사용 핸들러로 BaseHTTPServer.HTTPServer는 매우 간단한 HTTP 서버의 "이용 효율과 신뢰성을 향상시킬 수있는 멀티 프로세스, 멀티 스레드 모드를 지원하기 위해 참고 ".
는이 아이디어에 따르면,로 주어진다 원래 하나에서 수정 된 멀티 스레드/멀티 프로세스 지원와 SimpleHTTPServer은 다음과 같습니다 예를 들어
$ python2.7 ModifiedSimpleHTTPServer.py
usage: ModifiedSimpleHTTPServer.py [-h] [--pydoc] [--port PORT]
[--type {process,thread}] [--root ROOT]
[--run]
Modified SimpleHTTPServer with MultiThread/MultiProcess and IP bind support.
Original: https://docs.python.org/2.7/library/simplehttpserver.html
Modified by: [email protected]
optional arguments:
-h, --help show this help message and exit
--pydoc show this module's pydoc
run arguments:
--port PORT specify server port (default: 8000)
--type {process,thread}
specify server type (default: 'thread')
--root ROOT specify root directory (default: cwd '/home/vbem')
--run run http server foreground
NOTE: stdin for input, stdout for result, stderr for logging
, ModifiedSimpleHTTPServer.py --run --root /var/log --type process
정적 멀티 프로세스 HTTP를 실행합니다 '/ var/log'를 루트 디렉토리로 사용하는 파일 서버입니다.
수정 된 코드는 다음과 같습니다
#! /usr/bin/env python2.7
# -*- coding: utf-8 -*-
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
r"""Modified SimpleHTTPServer with MultiThread/MultiProcess and IP bind support.
Original: https://docs.python.org/2.7/library/simplehttpserver.html
Modified by: [email protected]
"""
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
import os, sys, pwd, posixpath, BaseHTTPServer, urllib, cgi, shutil, mimetypes, socket, SocketServer, BaseHTTPServer
from cStringIO import StringIO
USERNAME = pwd.getpwuid(os.getuid()).pw_name
HOSTNAME = socket.gethostname()
PORT_DFT = 8000
class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
server_version = "SimpleHTTP/0.6"
def do_GET(self):
f = self.send_head()
if f:
self.copyfile(f, self.wfile)
f.close()
def do_HEAD(self):
f = self.send_head()
if f:
f.close()
def send_head(self):
path = self.translate_path(self.path)
f = None
if os.path.isdir(path):
if not self.path.endswith('/'):
self.send_response(301)
self.send_header("Location", self.path + "/")
self.end_headers()
return None
for index in "index.html", "index.htm":
index = os.path.join(path, index)
if os.path.exists(index):
path = index
break
else:
return self.list_directory(path)
ctype = self.guess_type(path)
try:
f = open(path, 'rb')
except IOError:
self.send_error(404, "File not found")
return None
self.send_response(200)
self.send_header("Content-type", ctype)
fs = os.fstat(f.fileno())
self.send_header("Content-Length", str(fs[6]))
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
self.end_headers()
return f
def list_directory(self, path):
try:
list = ['..'] + os.listdir(path) #
except os.error:
self.send_error(404, "No permission to list directory")
return None
list.sort(key=lambda a: a.lower())
f = StringIO()
displaypath = cgi.escape(urllib.unquote(self.path))
f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
f.write("<html>\n<title>%s %s</title>\n<body>" % (HOSTNAME, displaypath))
f.write("%[email protected]%s:<strong>%s</strong>\n" % (USERNAME, HOSTNAME, path.rstrip('/')+'/'))
f.write("<hr>\n<ul>\n")
for name in list:
fullname = os.path.join(path, name)
displayname = linkname = name
if os.path.isdir(fullname):
displayname = name + "/"
linkname = name + "/"
if os.path.islink(fullname):
displayname = name + "@"
f.write('<li><a href="%s">%s</a>\n'
% (urllib.quote(linkname), cgi.escape(displayname)))
f.write("</ul>\n<hr>\n<pre>%s</pre>\n</body>\n</html>\n" % __doc__)
length = f.tell()
f.seek(0)
self.send_response(200)
encoding = sys.getfilesystemencoding()
self.send_header("Content-type", "text/html; charset=%s" % encoding)
self.send_header("Content-Length", str(length))
self.end_headers()
return f
def translate_path(self, path):
path = path.split('?',1)[0]
path = path.split('#',1)[0]
path = posixpath.normpath(urllib.unquote(path))
words = path.split('/')
words = filter(None, words)
path = os.getcwd()
for word in words:
drive, word = os.path.splitdrive(word)
head, word = os.path.split(word)
if word in (os.curdir, os.pardir): continue
path = os.path.join(path, word)
return path
def copyfile(self, source, outputfile):
shutil.copyfileobj(source, outputfile)
def guess_type(self, path):
base, ext = posixpath.splitext(path)
if ext in self.extensions_map:
return self.extensions_map[ext]
ext = ext.lower()
if ext in self.extensions_map:
return self.extensions_map[ext]
else:
return self.extensions_map['']
if not mimetypes.inited:
mimetypes.init()
extensions_map = mimetypes.types_map.copy()
extensions_map.update({'': 'text/plain'})
class ProcessedHTTPServer(SocketServer.ForkingMixIn, BaseHTTPServer.HTTPServer):
r"""Handle requests in multi process."""
class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
r"""Handle requests in a separate thread."""
SERVER_DICT = {
'thread' : ThreadedHTTPServer,
'process' : ProcessedHTTPServer,
}
SERVER_DFT = 'thread'
def run(sCwd=None, sServer=SERVER_DFT, nPort=PORT_DFT, *lArgs, **dArgs):
r"""
"""
sys.stderr.write('start with %r\n' % sys._getframe().f_locals)
if sCwd is not None:
os.chdir(sCwd)
cServer = SERVER_DICT[sServer]
oHttpd = cServer(("", nPort), SimpleHTTPRequestHandler)
sys.stderr.write('http://%s:%s/\n' % (HOSTNAME, nPort))
oHttpd.serve_forever()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# main
def _main():
r"""Main.
"""
import argparse
oParser = argparse.ArgumentParser(
description = __doc__,
formatter_class = argparse.RawTextHelpFormatter,
epilog = 'NOTE: stdin for input, stdout for result, stderr for logging',
)
oParser.add_argument('--pydoc', action='store_true',
help = "show this module's pydoc",
)
oGroupR = oParser.add_argument_group(title='run arguments', description='')
oGroupR.add_argument('--port', action='store', type=int, default=PORT_DFT,
help = 'specify server port (default: %(default)r)',
)
oGroupR.add_argument('--type', action='store', default=SERVER_DFT, choices=SERVER_DICT.keys(),
help = 'specify server type (default: %(default)r)',
)
oGroupR.add_argument('--root', action='store', default=os.getcwd(),
help = 'specify root directory (default: cwd %(default)r)',
)
oGroupR.add_argument('--run', action='store_true',
help = '\n'.join((
'run http server foreground',
)))
oArgs = oParser.parse_args()
if oArgs.pydoc:
help(os.path.splitext(os.path.basename(__file__))[0])
elif oArgs.run:
return run(sCwd=oArgs.root, sServer=oArgs.type, nPort=oArgs.port)
else:
oParser.print_help()
return 1
return 0
if __name__ == "__main__":
exit(_main())
한편, 200 선으로 하나의 파이썬 파일은 "파이썬에 "와 "경량"요구를 충족 할 수 있습니다.
마지막으로,이 ModifiedSimpleHTTPServer.py
은 일시적인 사용을 위해 손으로 "킬러 응용 프로그램"일 수 있지만 Nginx는 장기간 사용하도록 권장됩니다.
이것은 실제로 파이썬에 대한 직업이 아닙니다. Nginx의 문제점은 무엇입니까? –
@DanielRoseman : Ngix가 Python 응용 프로그램으로 패키지하고 배포하는 것이 덜 실용적이라고 상상할 수 있습니다. – Hubro
@DanielRoseman 나는 파이썬 기반의 가볍고 가능한 한 효율적인 것을 필요로하기 때문에. 작은 패키지를 쓰고 있는데 Nginx와 같은 외부 종속성에 의존하지 않고 정적 파일 제공을 번들로 제공하고 싶습니다. – Marconi