6

I was trying out python -mtimeitso I put python -mtimeit "n = 0; while n < 10: pass" Then an invalid syntax error showed up. same with semicolon and for loop.

However, when I try semicolon and loop individually. Both worked fine.

python -c "for i in range(10): print(n)"  
python -c "n = 1; n = 2; print(n)"

Why is this so and how can I test while loop in timeit? Thank you very much!

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Mike Lee
  • 1,215
  • 3
  • 10
  • 22

5 Answers5

12

while, for can't have semicolon before, they need to be on one line. If you looked at Python grammar:

compound_stmt ::=  if_stmt
                   | while_stmt
                   | for_stmt
                   | try_stmt
                   | with_stmt
                   | funcdef
                   | classdef
                   | decorated
suite         ::=  stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement     ::=  stmt_list NEWLINE | compound_stmt
stmt_list     ::=  simple_stmt (";" simple_stmt)* [";"]

you will see that the statements that are part of compound_stmt need to be one one line alone. The only statements that can be separated by semicolon are simple_stmt group:

simple_stmt ::=  expression_stmt
                 | assert_stmt
                 | assignment_stmt
                 | augmented_assignment_stmt
                 | pass_stmt
                 | del_stmt
                 | print_stmt
                 | return_stmt
                 | yield_stmt
                 | raise_stmt
                 | break_stmt
                 | continue_stmt
                 | import_stmt
                 | global_stmt
                 | exec_stmt
3

timeit can take two parameters: the setup code and the code to time.

python -mtimeit "n = 0" "while n < 10: pass"

Also, you should change that pass to n += 1 or you'll be in an infinite loop.

Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
  • `timeit` works [fine](http://docs.python.org/2/library/timeit.html#command-line-interface) with one argument. The issue is one of syntax. – Cairnarvon Sep 04 '13 at 00:17
  • @Cairnarvon: It's obviously not working fine with the one argument that the OP gave, while it does work with the two argument form I gave. Good job, down-voting the only answer that actually solved the problem. – Ethan Furman Sep 04 '13 at 01:41
  • Your answer doesn't solve anything, because it misses the point of the question. The problem is *not* that `timeit` can *optionally* take more than one argument, or even strictly about `timeit` in the first place. The other two answers give a proper solution and an explanation of the actual problem. – Cairnarvon Sep 04 '13 at 07:21
  • 2
    @Cairnarvon: I was incorrect about being the only solution that worked -- Aleks' answer does as well. Out of curiousity, what is "improper" about my solution to the OP's question of `how can I test while loop in timeit?` – Ethan Furman Sep 04 '13 at 13:08
1

If you're writing it in a script, why don't you indent it just the way you would do it in a real python program? Like this:

python -mtimeit "
n = 0
while n < 10:
    pass"
Aleks-Daniel Jakimenko-A.
  • 10,335
  • 3
  • 41
  • 39
1

The selected answer superbly tackles the why, but not the question of how this can be worked around under any operating system (since windows cmd doesn't allow multi-line statements)

The answer is: exec

You have to nest any loops in an exec statement.

Examples: (Python 2)

python -c "i = 3; while i:print i; i-=1"

is a syntax error, while

python -c "i = 3; exec 'while i:print i;i-=1'"

works correctly.

Tzalumen
  • 652
  • 3
  • 16
1

It is an old topic but no one mentioned list comprehensions so here it is.

A list comprehension with a function could also be used, if printing is involved:

python2 -m timeit "from pprint import pprint; [pprint(i) for i in range(1000)]"

In python3 print itself would work because unlike python2 it is already a function:

python3 -m timeit "[print(i) for i in range(1000)]"