Skip to content

vmprofshow breaks on multiline dictionary comprehensions #118

@jogo

Description

@jogo

Using cpython 2.7

test.py:

def foo():
    a = {
        i: i**i
        for i in range(10000)}
    print "END"

foo()
$ python -m vmprof --lines -o test.prof test.py
END
$ vmprofshow --lines test.prof
Total hits: 1480 s
File: test.py
Function: <dictcomp> at line 3
Traceback (most recent call last):
  File "/usr/local/bin/vmprofshow", line 11, in <module>
    sys.exit(main())
  File "/usr/local/lib/python2.7/dist-packages/vmprof/show.py", line 159, in main
    pp.show(args.profile)
  File "/usr/local/lib/python2.7/dist-packages/vmprof/show.py", line 182, in show
    self.show_func(filename, funline, funname, line_stats)
  File "/usr/local/lib/python2.7/dist-packages/vmprof/show.py", line 234, in show_func
    sublines = inspect.getblock(all_lines[start_lineno-1:])
  File "/usr/lib/python2.7/inspect.py", line 677, in getblock
    tokenize.tokenize(iter(lines).next, blockfinder.tokeneater)
  File "/usr/lib/python2.7/tokenize.py", line 169, in tokenize
    tokenize_loop(readline, tokeneater)
  File "/usr/lib/python2.7/tokenize.py", line 175, in tokenize_loop
    for token_info in generate_tokens(readline):
  File "/usr/lib/python2.7/tokenize.py", line 357, in generate_tokens
    raise TokenError, ("EOF in multi-line statement", (lnum, 0))
tokenize.TokenError: ('EOF in multi-line statement', (6, 0))

Specifically the line i: i**i takes the most time. But when handling a tokenize error the same way as a file missing I get:

Total hits: 1480 s
File: test.py
Function: <dictcomp> at line 3

Line #     Hits   % Hits  Line Contents
=======================================
     3        1      0.1
     4     1479     99.9

Total hits: 1481 s
File: test.py
Function: <module> at line 1

Line #     Hits   % Hits  Line Contents
=======================================
     1                    def foo():
     2                        a = {
     3                            i: i**i
     4                            for i in range(10000)}
     5                        print "END"

Total hits: 2 s

Could not find file -
Are you sure you are running this program from the same directory
that you ran the profiler from?
Continuing without the function's contents.

Line #     Hits   % Hits  Line Contents
=======================================
     0        2    100.0

Total hits: 1480 s
File: test.py
Function: foo at line 1

Line #     Hits   % Hits  Line Contents
=======================================
     1                    def foo():
     2                        a = {
     3                            i: i**i
     4     1480    100.0          for i in range(10000)}
     5                        print "END"

Total hits: 1 s

I tried playing around with inspect.getblock for dictionary comprehension by hand and was unable to get it to work properly.

So I am not sure that multiline dictionary comprehensions are measured correctly per line.

At the very least we can prevent vmprofshow --lines test.prof from crashing by handling the tokenize error in vmprof.show.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions