Python command line argument semicolon-loop error
Asked Answered
G

5

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!

Gerrilee answered 3/9, 2013 at 21:54 Comment(2)
python -mtimeit -c "n = 1; n = 2; print(n)" ?Liverwurst
No need to be so apologetic!Potency
L
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
Lundt answered 3/9, 2013 at 22:34 Comment(0)
M
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.

Maddox answered 4/9, 2013 at 0:4 Comment(4)
timeit works fine with one argument. The issue is one of syntax.Annulment
@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.Maddox
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.Annulment
@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?Maddox
S
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"
Strove answered 3/9, 2013 at 21:57 Comment(0)
C
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.

Christophany answered 13/12, 2017 at 21:51 Comment(0)
F
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)]"
Flint answered 28/11, 2021 at 14:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.