2011-07-14 15 views
35

結果変数をメモリに保持する方法はないので、スクリプトの先頭を実行するたびに再計算する必要はありませんか? 私はスクリプトを実行するたびに、(ディスクから読み込んでいる)データセットに対して、(5〜10秒)一連の厳密な操作を行っています。 インタラクティブなエディタを使用して実行間でコードをデバッグするのが得意なので、これはあまり問題にはなりません。しかし、時にはインタラクティブな機能だけではそれをカットしません。Pythonスクリプトの実行間に永続変数を保持する

私は結果をディスク上のファイルに書き込むことができると知っていますが、可能ならばそうしないでください。これは、スクリプトを初めて実行するときに変数を生成するソリューションでなければなりません。また、シェル自体が閉じられるまで、または明示的にそれが外に出るまで、メモリ内に保持します。このような何か:

# Check if variable already created this session 
in_mem = var_in_memory() # Returns pointer to var, or False if not in memory yet 
if not in_mem: 
    # Read data set from disk 
    with open('mydata', 'r') as in_handle: 
     mytext = in_handle.read() 
    # Extract relevant results from data set 
    mydata = parse_data(mytext) 
    result = initial_operations(mydata) 
    in_mem = store_persistent(result) 

私はshelveモジュールは、私がここを探していますが、棚の変数を開くために私は、ファイル名を指定しなければならないように見えるんだかもしれないものという暗示をしました永続オブジェクトなので、私が探しているものであるかどうかは分かりません。

私はそれをやりたい棚を得るためのヒントを教えてください。任意の代替アイデア?

答えて

29

reloadグローバル関数を使用して、メインスクリプトのコードを再実行すると、このようなことが実現できます。メインスクリプトをインポートし、キャッシュする変数を要求し、ラッパースクリプトのモジュールスコープ内にそのコピーをキャッシュし、必要なときに(stdinなどで何かを入力したときに)、ラッパースクリプトを作成する必要があります)、それはreload(yourscriptmodule)を呼び出しますが、今回はキャッシュされたオブジェクトに渡して、yourscriptが高価な計算をバイパスできるようにします。ここに簡単な例があります。

wrapper.py

import sys 
import mainscript 

part1Cache = None 
if __name__ == "__main__": 
    while True: 
     if not part1Cache: 
      part1Cache = mainscript.part1() 
     mainscript.part2(part1Cache) 
     print "Press enter to re-run the script, CTRL-C to exit" 
     sys.stdin.readline() 
     reload(mainscript) 

mainscript.py

def part1(): 
    print "part1 expensive computation running" 
    return "This was expensive to compute" 

def part2(value): 
    print "part2 running with %s" % value 

wrapper.pyが実行されている間、あなたは、mainscript.pyを編集part2関数に新しいコードを追加して実行できるようにすることができます事前計算されたpart1Cacheに対する新しいコード。

+3

外部ソースを実行する例外ハンドラを追加することを検討します。 – mehmetminanc

+1

mainscript.pyの依存関係が更新されたらどうなりますか?明示的にリロードする必要がありますか? – pomber

+0

os.environに変数を格納するには不十分でしょうか? – Ladmerc

3

Pythonのshelveは、ピクルされた(シリアル化された)オブジェクトの永続化ソリューションであり、ファイルベースです。利点は、Pythonオブジェクトを直接格納することです。つまり、APIは非常に簡単です。

ディスクを避けたい場合、探しているテクノロジは「メモリ内のデータベース」です。いくつかの選択肢がありますので、この質問を参照してください:in-memory database in Python

+1

ありがとう、他のアプリケーションには適していますが、私のニーズにはあまりにも強すぎるようです。 –

4

メモリ内のデータを保持するには、プロセスを継続して実行する必要があります。メモリは、シェルではなくスクリプトを実行するプロセスに属します。シェルはあなたのためにメモリを保持することはできません。

コードを変更してプロセスを実行し続ける場合は、モジュールが変更されたときにモジュールをリロードする必要があります。メモリ内のデータのいずれかが変更されるクラスのインスタンスである場合、そのクラスを新しいクラスのインスタンスに変換する方法を見つける必要があります。それはちょっと混乱している。この種のホットパッチ(Common Lispが思い浮かぶ)には多少の言語はあまり良くなかったし、事態が悪くなる可能性も非常に高い。

+0

有益な答えをありがとうございます。特定のソリューションが私の望むように機能しない理由を知ってうれしいです。私はあなたの説明に感謝します。 –

5

将来のセッションで1つのオブジェクト(またはオブジェクトグラフ)のみを保持したい場合、shelveモジュールはおそらく過剰です。あなたが気にしているオブジェクトを漬けてください。ピクルファイルがない場合は作業を行い、ピックルを保存するか、ピクルファイルがある場合は読み込みます。

import os 
import cPickle as pickle 

pickle_filepath = "/path/to/picklefile.pickle" 

if not os.path.exists(pickle_filepath): 
    # Read data set from disk 
    with open('mydata', 'r') as in_handle: 
     mytext = in_handle.read() 
    # Extract relevant results from data set 
    mydata = parse_data(mytext) 
    result = initial_operations(mydata) 
    with open(pickle_filepath, 'w') as pickle_handle: 
     pickle.dump(result, pickle_handle) 
else: 
    with open(pickle_filepath) as pickle_handle: 
     result = pickle.load(pickle_handle) 
+0

ピクルスもシェルフより速い傾向があります – pufferfish

0

これは可能ですが、Pythonシェルを使用する必要があります。つまり、Pythonスクリプトを起動するために使用するシェルは、Pythonのプロセスでなければなりません。その後、シェルを閉じるまで、グローバル変数またはクラスは存続します。

cmdモジュールを見ると、シェルプログラムを簡単に書くことができます。あなたのシェルで実装されていないコマンドが(シェルを閉じずに)実行するためにシステムシェルに渡されるように手配することもできます。次に、runpyモジュールを使用してPythonスクリプトを実行するコマンド、例えばprunを実装する必要があります。

http://docs.python.org/library/runpy.html

あなたは、プログラムの名前空間に理想的な辞書や単一クラスのインスタンスをあなたの特別なデータを渡すためにinit_globalsパラメータを使用する必要があります。

1

これはこれは、あなたが何かをコピーまたは再計算することなく、第1のプロセスの変数を変更して再定義することができます...

$mkfifo inpipe 

#/usr/bin/python3 
#firstprocess.py 
complicated_calculation() 
while True: 
with open('inpipe') as f: 
    try: 
    print(exec (f.read())) 
    except Exception as e: print(e) 

$./first_process.py & 
$cat second_process.py > inpipe 

OS依存のソリューションです。マルチプロセッシング、memcached、pickle、shelveモジュール、またはデータベースと比較して、最も効率的なソリューションでなければなりません。

second_process.pyをエディタまたはIDEで繰り返し編集して再定義する場合は、最初のプロセス(大規模なdictなどの初期化など)を待つことなくあなたが変更を行う時。

0

osは/ calcsをロードし、定期的にsqlデータをある種のメモリ構造にリロードしてから、他のスクリプトのメモリ内データをソケット。

関連する問題