2017-11-29 15 views
1

코드를 임의로 일괄 적으로 생성하는 프로그램을 만들고 입력이 있으면 해당 코드가 원하는 출력을 생성하는지 테스트합니다. 생성 된 코드의 배치를 꽤 크게 만들고 싶습니다. 배치 당 파일을 무작위로 생성하는 10,000 개를 만들고 싶습니다. 그래서 디스크에 쓰기를하는 대신 메모리 내에서 작업하고 싶습니다. 나는 또한 컴파일러가 나를 위해 모든 작업을 수행하기를 원한다. 일단 생성 된 파일을 모듈로 가져온 다음 해당 모듈에서 함수를 생성하고 결과를 원하는 출력에 대해 테스트한다.가상 디렉토리 또는 Python 메모리에서 코드 실행 3

파이썬에 tempfile.SpooledTemporaryFile()이 있는데, 파일과 비슷한 객체를 만들고 조작 할 수 있지만 일단 생성되면 파이썬 스크립트 인 것처럼 액세스하려고합니다. 그러나 파일이 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의 기능을 탐색 중입니다. 쉘 외부에서 어떻게 응답할지는 확실하지 않습니다. 나는 그것이 효과가 있기를 바라고 있지만, 우리는 보게 될 것입니다.

내가 시도하고있는 것을 수행하는 올바른/더 좋은 방법이 있습니까? 더 구체적으로, 컴파일러가 메모리에 존재하는 파일의 방향을 가리 키도록하여 기존 파일이었던 것처럼 그리고/또는 실행될 수 있도록하는 방법이 있습니까? 아니면 파이썬 형식의 문자열, 그것은 반드시 문자열 형태로 실행할 수있는 파일 일 필요는 없습니다.

답변

0

https://stackoverflow.com/a/2849077/6047611 필요한 정보 나 제공

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

가 내장 된 간부() 함수를 사용하여이 솔루션을 만드는 (SpooledTemporaryFile로 조작되는 경우) :

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()에 최대 문자 제한이 없기 때문에 심각한 문제가 발생할 수 있습니다.

생성 된 코드를 열거 나 실행하는 데 필요한 가져 오기 명령문이없고 실행시 여러 번 실행할 수 있습니다. 마운트 된 가상 디렉터리 또는 일반적으로 파일 개체까지 포함 할 수 있습니다.