如何提高python导入速度?

时间:2016-08-23 11:50:34

标签: python performance python-import

这个问题多次被问过SO(例如here),但还没有真正的答案。

我正在编写一个用于呈现模板的简短命令行工具。它是使用Makefile:

进行的
i = $(wildcard *.in)
o = $(patsubst %.in, %.out, $(t))

all: $(o)

%.out: %.in
    ./script.py -o $@ $<

在这个虚拟示例中,Makefile会解析每个.in文件以生成.out文件。使用make非常方便,因为我在此脚本之前和之后有很多其他操作要触发。此外,我希望尽可能保持KISS

  

因此,我希望保持我的工具简单,愚蠢,并使用语法script -o out in分别处理每个文件

我的脚本使用以下内容:

#!/usr/bin/env python
from jinja2 import Template, nodes
from jinja2.ext import Extension
import hiyapyco
import argparse
import re   

...

问题是每次执行花费我大约1.2s(处理时间约为60ms,导入指令约为1140ms):

$ time ./script.py -o foo.out foo.in
real    0m1.625s
user    0m0.452s
sys     0m1.185s

我的Makefile对100个文件的整体执行是荒谬的:~100个文件x 1.2s = 120s。

这不是解决方案,但这应该是解决方案。

我可以使用哪种替代方案?

修改

我喜欢Python,因为它的语法可读性和社区规模。在这种特殊情况下(命令行工具),我不得不承认Perl仍然是一个不错的选择。用Perl编写的相同脚本(也是一种解释语言)大约快12倍(使用Text::Xslate)。

我不想以任何方式推广Perl我只是想用Python来解决我最大的问题:由于导入时间不长,它还不适合简单的命令行工具。

4 个答案:

答案 0 :(得分:3)

这并不容易,但您可以将程序转换为后台程序并处理命令来处理文件。

另一个程序可以将处理命令提供给它,从而使真正的开始变得非常容易。

答案 1 :(得分:1)

将模板部件写为单独的过程。第一次运行“script.py”时,它将启动这个单独的进程。一旦进程存在,它就可以通过命名管道传递输入/输出文件名。如果进程没有输入x秒,它会自动退出。 x的大小取决于您的需求

因此,参数通过script.py写入命名管道传递给长时间运行的进程。导入只发生一次(假设输入相当频繁),而BPL指出这会使一切运行得更快

答案 2 :(得分:0)

您可以使用glob对所需文件执行该操作。

import glob
in_files=glob.glob('*.in') 
out_files=glob.glob('*.out') 

因此,您处理同一脚本中的所有文件,而不是每次都使用每对文件调用脚本。至少你不必每次都开始python。

答案 3 :(得分:0)

问题显而易见,现在你得到了:

cost(file) = 1.2s = 60ms + 1040ms,表示:

cost(N*files) = N*1.2s

现在,你为什么不把它变成:

cost1(files) = 1040ms + N*60ms

这样,理论上处理100个文件将是7,04s而不是120s

修改

因为我收到了这个问题的投票,我会发一个小例子,让我们假设你有这个python文件:

# foo.py
import numpy
import cv2

print sys.argv[0]

我的盒子上的执行时间是1.3秒,现在,如果我这样做:

for /l %x in (1, 1, 100) do python foo.py

我将获得100 * 1.3s的执行时间,我的建议是将foo.py转为:

import numpy
import cv2

def whatever_rendering_you_want_to_do(file):
    pass

for file in sys.argv:
    whatever_rendering_you_want_to_do(file)

这样您只能导入一次而不是100次