Python 3.x 为python 3装载虚拟目录或在内存中运行代码

Python 3.x 为python 3装载虚拟目录或在内存中运行代码,python-3.x,memory,generated-code,Python 3.x,Memory,Generated Code,我正在制作一个程序,它可以批量随机生成代码,并且给定一个输入,测试代码是否生成所需的输出。我想让生成的代码批相当大,比如说每批10000个随机生成的文件,所以我想在内存中工作,而不是把它们写入磁盘。我还希望编译器为我完成所有工作,文件创建后作为模块导入,然后运行该模块中生成的函数,并根据所需的输出测试结果 我发现Python有tempfile.SpooledTemporaryFile(),这将允许我创建和操作一个类似文件的对象,但一旦创建,我希望像访问Python脚本一样访问它。然而,由于文件在

我正在制作一个程序,它可以批量随机生成代码,并且给定一个输入,测试代码是否生成所需的输出。我想让生成的代码批相当大,比如说每批10000个随机生成的文件,所以我想在内存中工作,而不是把它们写入磁盘。我还希望编译器为我完成所有工作,文件创建后作为模块导入,然后运行该模块中生成的函数,并根据所需的输出测试结果

我发现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)
导入操作系统、tempfile、importlib、desiredAndOut、codeGenerator
GeneratedCodeAsString=codeGenerator.generateCode()
cwd=os.getcwd()
成功代码=[]
batchSize=int(输入(输入所需的批次大小:))
运行次数=0
运行<批处理大小时:
使用tempfile.SpooledTemporaryFile(10240,'w+b',None,None,'\n','.py','tmp',cwd)作为stf:
write(generatedCodeAsAsAsAsAsString.encode())
导入tmp#导入新生成的文件(可能在cwd中有“快捷方式”?)
importlib.invalidate_caches()#确保编译器第一次运行时知道有一个新模块
importlib.reload(tmp)#如果编译器变得聪明,并从此循环的第一次导入/第一次迭代中重新使用模块,请确保它重新加载/更新模块以匹配刚刚创建的新文件
out=tmp.generatedFunction(desiredAndout.GIVEN_输入)
如果out==DesiredAndOUT.DESIRED\u输出:
successfulCode.append(GeneratedCodeAsString+'\n'+'#批处理文件编号'+str(运行))
运行次数+=1
打印(成功代码)
尽管我做了很多努力,但tmp文件并没有链接到当前的工作目录,所以上面的导入无法工作。我需要找到一种方法,将该临时文件的内存地址提供给import语句,在那里它需要一个标准的'/foo/bar/tmp.py',并确保它将其解释为一个文件

由于权限问题,不能直接在计算机上安装虚拟驱动器。如果你知道一种在python中不需要管理员访问计算机就可以做这样的事情,我洗耳恭听。我目前正在探索内置函数exec的功能——不确定它在shell之外将如何响应。我希望它能起作用,但我们拭目以待

有没有正确/更好的方法来做我正在尝试的事情?更具体地说,是否有一种方法可以将编译器指向内存中现有文件的方向,从而可以像处理现有文件和/或运行文件一样对其进行操作?或者一个python格式的字符串,如果我可以以字符串形式运行它,它不一定需要是一个文件。

(如果作为SpooledTemporaryFile操作)

为我提供了使用内置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,因此它不“返回”结果,而是打印结果,我可以通过在生成的代码运行时将sys.stdout切换为新的StringIO,并在完成后将其切换回正常状态,来获得它打印的内容,然后获取StringIO对象的内容。如果需要文件格式,那么可以使用tempfile.SpooledTemporaryFile轻松完成,请参阅上面的第一个链接,但我已经将代码生成为字符串,因此无需首先将其转换为文件格式来运行它。我希望exec()没有最大字符数限制,这可能会导致重大问题

打开/运行生成的代码不需要导入语句,并且可以多次运行,而不会影响已装入的虚拟目录,甚至不会影响一般的文件对象。

(如果作为SpooledTemporaryFile进行操作)

为我提供了使用内置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,因此它不“返回”结果,而是打印结果,我可以通过在生成的代码运行时将sys.stdout切换为新的StringIO,并在完成后将其切换回正常状态,来获得它打印的内容,然后获取StringIO对象的内容。如果需要文件格式,那么可以使用tempfile.SpooledTemporaryFile轻松完成,请参阅上面的第一个链接,但我已经将代码生成为字符串,因此无需首先将其转换为文件格式来运行它。我希望exec()没有最大字符数限制,这可能会导致重大问题

打开/运行生成的代码不需要任何导入语句,并且可以多次运行,而不会弄乱已装入的虚拟目录,甚至通常不会弄乱文件对象