8

背景:私はサーバーに関しては完全な初心者ですが、Pythonでプログラミングする方法を知っています。

基本的なPython2.7モジュール(SimpleHTTPServer、CGIHTTPServerなど)を使用して単純なサーバーをセットアップしようとしています。このサーバーは、起動時にファイルから数GBのデータを含むグローバルな読み取り専用変数をロードする必要があります。次に、各ユーザーがページにアクセスすると、サーバーはビッグデータを使用して出力を生成し、それがユーザーに提供されます。

names.txt例として、英語のすべての可能な適切な名詞を含む4GBのファイルがあると仮定します。

Jack
John
Allison
Richard
...

私の目標が名前のリスト全体をメモリに読み込んでから、この適切な名詞の大きなリストからランダムに1つの名前を選択することであると仮定しましょう。私は現在、PythonのネイティブCGIHTTPServerモジュールを使用してこれを実現できます。まず、ターミナルから実行して、CGIHTTPServerモジュールを直接実行します。

python -m CGIHTTPServer

次に、誰かがアクセスするwww.example-server.net:8000/foo.pyと、これらの名前の1つがランダムに与えられます。私は次のコードを持っていますfoo.py

#!/usr/bin/env python

import random

name_list = list()
FILE = open('names.txt','r')
for line in FILE:
    name = line[:-1]
    name_list.append(name)

FILE.close()
name_to_return = random.choice(name_list)

print "Content-type: text/html"
print
print "<title>Here is your name</title>"
print "<p>" + name_to_return + "</p>"

これは私が望むことをします。ただし、アクセスするたびにサーバーに4 GBのファイルの再読み取りが強制されるため、非常に非効率的です。

これを効率的なプロセスにするにはどうすればよいname_listですか。サーバーが起動するとすぐに変数がグローバルとして作成され、各アクセスはその変数からのみ読み取ります。

4

4 に答える 4

6

将来の参考のために、誰かが同じ問題に直面した場合:私は最終的にCGIHTTPServerのリクエストハンドラーをサブクラス化し、新しいdo_POST()関数を実装しました。グローバル変数なしで動作するCGIスクリプトがある場合は、次のような方法で開始できます。

import CGIHTTPServer
import random
import sys
import cgi

class MyRequestHandler(CGIHTTPServer.CGIHTTPRequestHandler):
    global super_important_list
    super_important_list = range(10)
    random.shuffle(super_important_list)

    def do_POST(s):    
        """Respond to a POST request."""
        form = cgi.FieldStorage(fp=s.rfile,headers=s.headers,environ={'REQUEST_METHOD':'POST','CONTENT_TYPE':s.headers['Content-Type'],})
        s.wfile.write("<html><head><title>Title goes here.</title></head>")
        s.wfile.write("<body><p>This is a test.</p>")
        s.wfile.write("<p>You accessed path: %s</p>" % s.path)
        s.wfile.write("<p>Also, super_important_list is:</p>")
        s.wfile.write(str(super_important_list))
        s.wfile.write("<p>Furthermore, you POSTed the following info: ")
        for item in form.keys():
            s.wfile.write("<p>Item: " + item)
            s.wfile.write("<p>Value: " + form[item].value)
        s.wfile.write("</body></html>")

if __name__ == '__main__':
    server_address = ('', 8000)
    httpd = CGIHTTPServer.BaseHTTPServer.HTTPServer(server_address, MyRequestHandler)
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        sys.exit()

誰かがフォームに入力してPOSTを実行するたびに、変数formはサイトのユーザーごとに異なる可能性のあるキーと値のペアを持つ辞書のようなオブジェクトになりますが、グローバル変数super_important_listはすべてのユーザーで同じになります。

私の質問に答えてくれたすべての人、特に私を正しい方向に向けてくれたMikeStederに感謝します。

于 2012-08-07T09:40:30.820 に答える
4

CGIは、各要求を処理するプロセスを生成することによって機能します。メモリにとどまるサーバープロセスを実行してHTTPリクエストを処理する必要があります。

変更されたBaseHTTPServerを使用して、独自のHandlerクラスを定義することができます。コードにデータセットを1回ロードすると、ハンドラーのdo_GETメソッドがランダムに1つを選択します。

個人的には、BaseHTTPServerよりもはるかに優れたIMOである単純なソリューションとして、CherryPyのようなものを検討します。CherryPy以外にも、ボトル、フラスコ、ツイスト、ジャンゴなどのオプションがたくさんあります。もちろん、このサーバーを他のWebサーバーの背後に配置する必要がある場合は、リバースプロキシを設定するか、CherryPyをWSGIとして実行することを検討する必要があります。アプリ。

于 2012-08-06T14:36:06.177 に答える
2

名前の値をデータベースに保存し、名前の先頭の文字に従って名前を保存することをお勧めします。次に、aとzの間の文字に対してランダムを実行し、そこから再度ランダム化して、ランダムな開始文字からランダムな名前を取得できます。

于 2012-08-06T14:34:10.670 に答える
2

プレフィックスツリー(別名トライ)を1回作成し、クエリを受信するたびにランダムウォークを生成します。

それはかなり効率的です。

于 2012-08-06T14:40:33.590 に答える