如何加速 exec() 的重复执行?
How to speed up a repeated execution of exec()?
我有以下代码:
for k in pool:
x = []
y = []
try:
exec(pool[k])
except Exception as e:
...
do_something(x)
do_something_else(y)
其中 pool[k]
是 python 代码,最终会将项目附加到 x
和 y
(这就是为什么我使用 exec
而不是 eval
).
我已经尝试用 pypy 执行相同的代码,但是对于这个特定的块我并没有好多少,exec
的那一行仍然是我的瓶颈。
也就是说,我的问题是:
exec
是否有更快的替代方案?
如果没有,在这种情况下您是否有任何解决方法来加快速度?
--更新--
澄清一下,pool
包含大约一百万个键,每个键都关联一个脚本(大约 50 行代码)。脚本的输入在 for loop
之前定义,脚本生成的输出存储在 x
和 y
中。因此,每个脚本在代码中都有一行说明 x.append(something)
和 y.append(something)
。该程序的其余部分将评估结果并对每个脚本进行评分。因此,我需要遍历每个脚本,执行它并处理结果。这些脚本最初存储在不同的文本文件中。 pool
是解析这些文件得到的字典
P.S。
使用预编译版本的代码:
for k in pool.keys():
pool[k] = compile(pool[k], '<string>', 'exec')
我的速度提高了 5 倍,虽然不多,但已经很不错了。我正在尝试其他解决方案...
如果您确实需要以这种方式执行某些代码,请使用 compile() 进行准备。
即不要将原始 Python 代码传递给 exec 但已编译的对象。在你的代码上使用 compile() 之前使它们成为 Python 字节编译对象。
但是,编写一个函数来执行您需要的输入参数(即对应于 x 和 y 的 pool[k] 和 return 结果会更有意义。
如果您从文件中获取代码,您也会遇到 IO 速度减慢的问题
应付。所以最好将这些文件编译成 *.pyc.
您可能会考虑在 Python2.
中使用 execfile()
在池中使用函数的想法:
template = """\
def newfunc ():
%s
return result
"""
pool = [] # For iterating it will be faster if it is a list (just a bit)
# This compiles code as a real function and adds a pointer to a pool
def AddFunc (code):
code = "\n".join([" "+x for x in code.splitlines()])
exec template % code
pool.append(newfunc)
# Usage:
AddFunc("""\
a = 8.34**0.5
b = 8
c = 13
result = []
for x in range(10):
result.append(math.sin(a*b+c)/math.pi+x)""")
for f in pool:
x = f()
我有以下代码:
for k in pool:
x = []
y = []
try:
exec(pool[k])
except Exception as e:
...
do_something(x)
do_something_else(y)
其中 pool[k]
是 python 代码,最终会将项目附加到 x
和 y
(这就是为什么我使用 exec
而不是 eval
).
我已经尝试用 pypy 执行相同的代码,但是对于这个特定的块我并没有好多少,exec
的那一行仍然是我的瓶颈。
也就是说,我的问题是:
exec
是否有更快的替代方案?
如果没有,在这种情况下您是否有任何解决方法来加快速度?
--更新--
澄清一下,pool
包含大约一百万个键,每个键都关联一个脚本(大约 50 行代码)。脚本的输入在 for loop
之前定义,脚本生成的输出存储在 x
和 y
中。因此,每个脚本在代码中都有一行说明 x.append(something)
和 y.append(something)
。该程序的其余部分将评估结果并对每个脚本进行评分。因此,我需要遍历每个脚本,执行它并处理结果。这些脚本最初存储在不同的文本文件中。 pool
是解析这些文件得到的字典
P.S。 使用预编译版本的代码:
for k in pool.keys():
pool[k] = compile(pool[k], '<string>', 'exec')
我的速度提高了 5 倍,虽然不多,但已经很不错了。我正在尝试其他解决方案...
如果您确实需要以这种方式执行某些代码,请使用 compile() 进行准备。
即不要将原始 Python 代码传递给 exec 但已编译的对象。在你的代码上使用 compile() 之前使它们成为 Python 字节编译对象。
但是,编写一个函数来执行您需要的输入参数(即对应于 x 和 y 的 pool[k] 和 return 结果会更有意义。
如果您从文件中获取代码,您也会遇到 IO 速度减慢的问题 应付。所以最好将这些文件编译成 *.pyc.
您可能会考虑在 Python2.
中使用 execfile()在池中使用函数的想法:
template = """\
def newfunc ():
%s
return result
"""
pool = [] # For iterating it will be faster if it is a list (just a bit)
# This compiles code as a real function and adds a pointer to a pool
def AddFunc (code):
code = "\n".join([" "+x for x in code.splitlines()])
exec template % code
pool.append(newfunc)
# Usage:
AddFunc("""\
a = 8.34**0.5
b = 8
c = 13
result = []
for x in range(10):
result.append(math.sin(a*b+c)/math.pi+x)""")
for f in pool:
x = f()