2017-11-29 6 views
1

コードをランダムに生成し、入力があれば、そのコードが目的の出力を生成するかどうかをテストします。私は生成されたコードのバッチを非常に大きくしたい、バッチごとにランダムに10,000個のファイルを生成すると言うので、ディスクに書き込むのではなくメモリ内で作業したいと思っています。私はまた、コンパイラが、作成したファイルをモジュールとしてインポートし、そのモジュールで関数を生成して実行し、その結果が目的の出力に対してテストされていることを確認してください。仮想ディレクトリをマウントする、またはPythonのメモリ内でコードを実行する3

私はPythonがtempfile.SpooledTemporaryFile()を持っていることがわかりました。ファイルのようなオブジェクトを作成して操作することはできますが、一度作成すると、Pythonスクリプトのようにアクセスしたいと思います。しかし、ファイルはRAM上にあり、一旦クローズされると削除されるので、私はこれを行う方法を見つけるのに苦労しています。私が望んだことは、このようなものです:私の努力にもかかわらず

import os, tempfile, importlib, desiredInAndOut, codeGenerator 
generatedCodeAsAString = codeGenerator.generateCode() 
cwd = os.getcwd() 
successfulCode = [] 
batchSize = int(input(Enter desired batch size:)) 
runs = 0 
while runs < batchSize: 
    with tempfile.SpooledTemporaryFile(10240, 'w+b', None, None, '\n', '.py', 'tmp', cwd) as stf: 
     stf.write(generatedCodeAsAsAString.encode()) 
     import tmp #import the newly generated file (that maybe has a 'shortcut' in the cwd? Somehow?) 
     importlib.invalidate_caches() #make sure the compiler knows that there is a new module for the first time this runs 
     importlib.reload(tmp) #if the compiler gets smart and re-uses the module from the first import/first iteration of this loop, make sure it reloads/updates it to match the new file that was just created 
     out = tmp.generatedFunction(desiredInAndOut.GIVEN_INPUT) 
     if out == desiredInAndOut.DESIRED_OUTPUT: 
      successfulCode.append(generatedCodeAsAString+'\n'+'#BATCHFILE NO '+str(runs)) 
     runs += 1 
print(successfulCode) 

、tmpファイルは、現在の作業ディレクトリにリンクされない方法であるので、上記のインポートは動作しません。私は、一時的なファイルのメモリアドレスを、 '/foo/bar/tmp.py'という標準を期待するimport文に送り、それをファイルとして解釈することを確認する方法を見つける必要があります。

コンピュータに仮想ドライブを直接マウントすることは、許可が困難なためオプションではありません。コンピュータに管理者権限を持たずにそのようなことをするインテル・パイソンの方法を知っていれば、私はすべて耳にします。私は現在、組み込み関数execの機能を探っています。シェルの外部でどのように応答するかはわかりません。私はそれがうまくいくことを望んでいるが、我々は見るだろう。

私が試していることを行う正しい/より良い方法はありますか?具体的には、コンパイラがメモリ内に存在するファイルの方向にコンパイラを向ける方法があるので、既存のファイルであるかのように操作できますか?または、Pythonでフォーマットされた文字列です。文字列形式で実行できるのであれば、必ずしもファイルである必要はありません。

答えて

0

https://stackoverflow.com/a/2849077/6047611(SpooledTemporaryFileとして操作した場合)

https://stackoverflow.com/a/3906309/6047611

ビルトインのexec()関数を使用して、このソリューションを作るために必要な情報を私に提供:

import sys 
from io import StringIO 

def main(): 
    GIVEN_INPUT = input('Enter input as an integer:') 
    code = "def main():\n\tinput = "+GIVEN_INPUT+"\n\tprint(input + 3)\nmain()" 
    #this code would be randomly generated elsewhere. As is, simply adds 3 to GIVEN_INPUT 

    old_stdout = sys.stdout 
    redirected_output = StringIO() 
    sys.stdout = redirected_output 

    exec(code)#, sys._getframe(1).f_globals, sys._getframe(1).f_locals) 

    sys.stdout = old_stdout 

    print('function completed') 
    OUTPUT = redirected_output.getvalue().strip() 
    print(OUTPUT+' is the result of:\n'+ code) 

main() 

要約すると、exec()は私が見ることができる値を返すことはできませんが、代わりにsys.stdoutに出力することができます結果を '返す'ことは結果を出力し、生成されたコードが実行されている間は新しいStringIOのsys.stdoutを切り替えて、出力を得ることができます。そのStringIOオブジェクトの内容ファイル形式にする必要がある場合は、tempfile.SpooledTemporaryFileを使って簡単に行うことができます。上の最初のリンクを参照してください。しかし、コードを文字列として生成していますので、まずファイル形式に変換する必要はありませんそれ。 exec()に最大文字数制限がないと、重大な問題が発生する可能性があります。

生成されたコードを開く/実行するためのインポートステートメントは必要ありません。何度も実行することができます。マウントされた仮想ディレクトリ、または一般的なファイルオブジェクトですらあります。

関連する問題