【问题标题】:Python stats: how do I write it to a (human readable) filePython stats:如何将其写入(人类可读的)文件
【发布时间】:2012-11-12 00:31:56
【问题描述】:

我正在使用 Python 的热门分析器:http://docs.python.org/2/library/hotshot.html

它显示了如何打印统计数据:

stats.print_stats(20)

但是我怎样才能把它放到一个文件中呢?我不确定如何获取这些信息,因此我可以使用 write() 将其写入文件。

编辑:

我想要以这种方式打印出来的易于阅读的结果:

stats = hotshot.stats.load("stones.prof")
stats.strip_dirs()
stats.sort_stats('time', 'calls')
stats.print_stats(20) 

所以它看起来像这样:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    3.295    3.295   10.090   10.090 pystone.py:79(Proc0)

(所以当我打开stones.prof时它看起来不像)

【问题讨论】:

    标签: python file-io profiling


    【解决方案1】:

    【讨论】:

    • 我试过了,那个文件不可读。我将编辑我的问题以使其更清楚。
    • 你总是可以redirect stdout to a file
    【解决方案2】:

    我最终重写了 print_stats() 函数,首先从 pstats.py 复制它。它返回一个字符串,然后可以将其写入文件。我没有测试每个 if-else 循环,只是它在我需要它的示例中有效。我把原来的行注释掉了。尽管该函数不再使用真正的“自我”,但我已将变量名称保持不变。

    stats = hotshot.stats.load("stones.prof")
    stats.strip_dirs()
    stats.sort_stats('time', 'calls')
    readable_str = xprint_stats(stats, 20)
    
    import pstats
    def xprint_stats(self, *amount):
        x = ""
        for filename in self.files:
            x += " " + filename
        #if self.files: print >> self.stream
        # ?
        indent = ' ' * 8
        for func in self.top_level:
            #print >> self.stream, indent, xfunc_get_function_name(func)
            x += indent + pstats.func_get_function_name(func)
    
        #print >> self.stream, indent, self.total_calls, "function calls",
        x +=  indent + str(self.total_calls) + " function calls" + " "
        if self.total_calls != self.prim_calls:
            #print >> self.stream, "(%d primitive calls)" % self.prim_calls,
            x += "(%d primitive calls)" % self.prim_calls + " "
        #print >> self.stream, "in %.3f seconds" % self.total_tt
        #print >> self.stream
        x +=  "in %.3f seconds" % self.total_tt + "\n"
        #width, list = stats.get_print_list(amount)
        msg, width, list = xget_print_list(stats, amount)
        x += msg
    
        if list:
            #self.print_title()
            x += "\n" + '   ncalls  tottime  percall  cumtime  percall filename:lineno(function)'
            x += "\n"
            for func in list:
                #self.print_line(func)
                x +=  xprint_line(self, func) + "\n"
    #        print >> self.stream
    #        print >> self.stream
        #return self
        return x
    
    def xprint_line(self, func):  
        x = ""
        cc, nc, tt, ct, callers = self.stats[func]
        c = str(nc)
        if nc != cc:
            c = c + '/' + str(cc)
    #    print >> self.stream, c.rjust(9),
    #    print >> self.stream, f8(tt),
        x +=  c.rjust(9) + " "
        x +=  pstats.f8(tt) + " "
        if nc == 0:
            #print >> self.stream, ' '*8,
           x +=  ' '*8 
        else:
            #print >> self.stream, f8(float(tt)/nc),
            x +=  pstats.f8(float(tt)/nc) + " "
        #print >> self.stream, f8(ct),
        x +=  pstats.f8(ct) + " "
        if cc == 0:
            #print >> self.stream, ' '*8,
            x +=  ' '*8
        else:
            #print >> self.stream, f8(float(ct)/cc),
            x +=   pstats.f8(float(ct)/cc) + " "
        #print >> self.stream, func_std_string(func)
        x +=  pstats.func_std_string(func) + " "
        return x
    
    def xget_print_list(self, sel_list):
        width = self.max_name_len
        if self.fcn_list:
            stat_list = self.fcn_list[:]
            msg = "   Ordered by: " + self.sort_type + '\n'
        else:
            stat_list = self.stats.keys()
            msg = "   Random listing order was used\n"
    
        for selection in sel_list:
            stat_list, msg = self.eval_print_amount(selection, stat_list, msg)
    
        count = len(stat_list)
    
        if not stat_list:
            return 0, stat_list
        #print >> self.stream, msg
        if count < len(self.stats):
            width = 0
            for func in stat_list:
                if  len(pstats.func_std_string(func)) > width:
                    width = len(pstats.func_std_string(func))
        #return width+2, stat_list
        return msg, width+2, stat_list
    

    【讨论】:

      【解决方案3】:

      输出重定向怎么样?

      import sys
      import pstats
      sys.stdout = open('readable.profile', 'w')
      p = pstats.Stats('input.profile')
      p.print_stats()
      

      【讨论】:

      • 很遗憾p.print_stats() 不使用sys.stdout 进行打印。如果你尝试这个,你会得到一个空文件,并且信息打印到控制台而不是文件。
      【解决方案4】:

      Stats 采用可选的“流”参数。只需打开一个文件并将打开的文件对象传递给 Stats 构造函数,如下所示。从那时起,任何对 print_stats() 的调用都将输出到您传递给构造函数的流中。希望这可以帮助。 :)

      with open('path/to/output', 'w') as stream:
          stats = pstats.Stats('path/to/input', stream=stream)
          stats.print_stats()
      

      【讨论】:

      • 以下代码对我有用:import StringIO;stream = StringIO.StringIO(); stats = pstats.Stats(fname, stream=stream); stats.print_stats();流.seek(0);打印 stream.read()
      【解决方案5】:

      您可以使用该库:pstats_print2list https://pypi.python.org/pypi/pstats_print2list

      pip install pstats_print2list 及用法:

      from pstats_print2list import get_pstats_print2list, print_pstats_list
      fname_stats = 'my_profiling_out.stats'
      pstats_list = get_pstats_print2list(
          os.path.expanduser(fname_stats),
          filter_fnames=['myfile1.py', 'myfile2.py', 'root_path1'],
          exclude_fnames=['dontshow.py', 'path_dont_show'],
          sort='cumulative',
          limit=5,
      )
      print_pstats_list(pstats_list)
      

      【讨论】:

        【解决方案6】:

        对于那些寻找另一种解决方案的人,我们可以将字符串数据放入 txt 文件。下面的代码将使用两个函数将两个数字相加,然后制作 Profile 数据,最后将其写入 out.txt 文件。

        main.py

        import cProfile
        import time
        import pstats
        from io import StringIO
        
        def add_slow(a, b):
            time.sleep(0.5)
            return a+b
        
        def add_fast(a, b):
            return a+b
        
        prof = cProfile.Profile()
        
        def main_func():
            arr = []
            prof.enable()
            for i in range(10):
                if i%2==0:
                    arr.append(add_slow(i,i))
                else:
                    arr.append(add_fast(i,i))
            prof.disable()
            #prof.print_stats(sort='time')
            prof.dump_stats("main_funcs.prof")
            return arr
        
        main_func()
        stream = StringIO();
        stats = pstats.Stats("main_funcs.prof", stream=stream); 
        stats.print_stats()
        stream.seek(0)
        print(16*'=',"RESULTS",16*'=')
        data = stream.read()
        print(data)
        myText = open('out.txt', 'w')
        myText.write(data)
        myText.close()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-11-13
          • 2013-05-24
          • 2017-01-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-25
          相关资源
          最近更新 更多