Re: How to use "while" within the command in -c option of python?

Discussion in 'Python' started by Etienne Robillard, Oct 13, 2012.

  1. On Fri, 12 Oct 2012 15:51:19 -0700
    Herman <> wrote:

    > python -c "import os; while True: print('hello')"
    > File "<string>", line 1
    > import os; while True: print('hello')
    > ^
    > SyntaxError: invalid syntax
    > --
    > http://mail.python.org/mailman/listinfo/python-list


    You get a syntax error since you didn't used tabs indents in your string
    which is normal for python AFAIK.
    Etienne Robillard, Oct 13, 2012
    #1
    1. Advertising

  2. On Fri, 12 Oct 2012 19:04:20 -0400, Etienne Robillard wrote:

    > On Fri, 12 Oct 2012 15:51:19 -0700
    > Herman <> wrote:
    >
    >> python -c "import os; while True: print('hello')" File "<string>",
    >> line 1
    >> import os; while True: print('hello')
    >> ^
    >> SyntaxError: invalid syntax
    >> --
    >> http://mail.python.org/mailman/listinfo/python-list

    >
    > You get a syntax error since you didn't used tabs indents in your string
    > which is normal for python AFAIK.


    Incorrect. Python lets you use either spaces or tabs for indents, and in
    this case the SyntaxError is BEFORE the missing indent. He gets
    SyntaxError because you can't follow a semicolon with a statement that
    begins a block. It's the `while` that causes the error, not the lack of
    indent. Here's an example with `if` and an indented block that also
    fails:


    [steve@ando ~]$ python -c "pass; pass"
    [steve@ando ~]$ python -c "pass; if True: pass"
    File "<string>", line 1
    pass; if True: pass
    ^
    SyntaxError: invalid syntax


    Solution: don't use semi-colons, use newlines.

    In this example, I use `Ctrl-Q ENTER` to insert a literal newline in the
    string, which shows as ^M. Note that you *cannot* just type ^ M (caret
    M), that won't work, it must be an actual control character.


    [steve@ando ~]$ python -c 'import time^Mwhile True:^M print("hello"); time.sleep(2)'
    hello
    hello
    hello
    Traceback (most recent call last):
    File "<string>", line 3, in <module>
    KeyboardInterrupt


    In this example I just hit the Enter key to insert a newline, and let the
    shell deal with it. The ">" marks are part of the shell's prompt.

    [steve@ando ~]$ python -c "import time
    > while True:
    > print('hello'); time.sleep(2)"

    hello
    hello
    hello
    Traceback (most recent call last):
    File "<string>", line 3, in <module>
    KeyboardInterrupt




    --
    Steven
    Steven D'Aprano, Oct 13, 2012
    #2
    1. Advertising

  3. Etienne Robillard

    Thomas Bach Guest

    On Sat, Oct 13, 2012 at 12:32:41AM +0000, Steven D'Aprano wrote:
    >
    > He gets SyntaxError because you can't follow a semicolon with a
    > statement that begins a block.


    Can someone provide a link on where to find this type of information?
    I was just hunting through “The Python Language Reference†and could
    not find anything explicit. The only thing I found is

    http://docs.python.org/reference/simple_stmts.html

    “Several simple statements may occur on a single line separated by
    semicolons.â€

    Anyways, this does not explicitly say “You shall not put a compound
    statement after a simple statement separated by a semicolon.â€, right?

    Regards,
    Thomas Bach.
    Thomas Bach, Oct 13, 2012
    #3
  4. On Sat, Oct 13, 2012 at 7:41 PM, Thomas Bach
    <-mainz.de> wrote:
    > On Sat, Oct 13, 2012 at 12:32:41AM +0000, Steven D'Aprano wrote:
    >>
    >> He gets SyntaxError because you can't follow a semicolon with a
    >> statement that begins a block.

    >
    > Can someone provide a link on where to find this type of information?
    > I was just hunting through “The Python Language Reference” and could
    > not find anything explicit. The only thing I found is
    >
    > http://docs.python.org/reference/simple_stmts.html
    >
    > “Several simple statements may occur on a single line separated by
    > semicolons.”
    >
    > Anyways, this does not explicitly say “You shall not put a compound
    > statement after a simple statement separated by a semicolon.”, right?


    It's more that Python treats simple and compound statements as
    completely separate beasts. You can combine simple statements on one
    line, but compound statements mustn't be.

    In my opinion, this is a major wart in Python syntax. You can argue
    all you like about how it reduces code clarity to put these sorts of
    things together, but that's a job for a style guide, NOT a language
    requirement. Most code won't put an assignment followed by an
    if/while/for, but when I'm working interactively, I often want to
    recall an entire statement to edit and reuse, complete with its
    initialization - something like (contrived example):

    >>> a=collections.defaultdict(int)
    >>> for x in open("RilvierRex.txt"): a[x]+=1


    Then I keep doing stuff, keep doing stuff, and then come back to this
    pair of lines. Since they're two lines, I have to recall them as two
    separate entities, rather than as an initializer and the code that
    uses it. Logically, they go together. Logically, they're on par with a
    list comprehension, which initializes, loops, and assigns, all as a
    single statement. But syntactically, they're two statements that have
    to go on separate lines.

    To force that sort of thing to be a single recallable statement, I can
    do stupid tricks like:

    >>> if True:

    a=collections.defaultdict(int)
    for x in open("RilvierRex.txt"): a[x]+=1

    but that only works in IDLE, not in command-line interactive Python.

    Note, by the way, that it's fine to put the statement _inside_ the for
    on the same line. It's even legal to have multiple such statements:

    >>> for x in (1,2,3): print(x); print(x);

    1
    1
    2
    2
    3
    3

    If there's any ambiguity, it would surely be that, and not the simple
    statement being first.

    Okay, rant over. I'll go back to being nice now. :)

    ChrisA
    Chris Angelico, Oct 13, 2012
    #4
  5. On Sun, Oct 14, 2012 at 3:38 AM, Joshua Landau
    <> wrote:
    > This here isn't a flaw in Python, though. It's a flaw in the command-line
    > interpreter. By putting it all on one line, you are effectively saying:
    > "group these". Which is the same as an "if True:" block, and some things
    > like Reinteract even supply a grouping block like "build".
    >
    > That said, because some shells suck it would be nice if:
    >>
    >> python -c "a=1\nif a:print(a)"

    >
    > worked (just for -c).


    Yes, that'd be nice. But it still leaves the big question of why
    Python requires \n to separate one statement from another. It IS a
    flaw in Python that it requires one specific statement separator in
    this instance, even though it'll accept two in another instance.

    Here's a side challenge. In any shell you like, start with this
    failing statement, and then fix it without retyping anything:

    sikorsky@sikorsky:~$ python -c "a=1; if a: print(a)"
    File "<string>", line 1
    a=1; if a: print(a)
    ^
    SyntaxError: invalid syntax

    In bash, I was unable to insert a newline into the quoted string. My
    only option was to backspace everything after the point where I wanted
    the newline, then hit enter, then retype the if. I'm curious to know
    if that's simply because I didn't think of (some bash feature), or
    alternatively, if there's another shell that would have made this
    easy.

    Back to the main point. In C-like languages, the newline is nothing
    special. (ECMAScript allows the omission of semicolons at end of line
    in many cases, but many style guides recommend using them anyway.) You
    can, if you so desire, put all your code into a single line. It's then
    up to the project's style guide to decide how things should be laid
    out. For instance, this is multiple statements in PHP, but I see it as
    one logical action:

    $bar=array(); for ($foo as $k=>$v) $bar[$k]="<p>".$v."</p>";

    It's one statement in Python:

    bar = ["<p>"+x+"</p>" for x in foo]

    It's one statement in Pike:

    array bar = map(foo,lambda(string x) {return "<p>"+x+"</p>";});

    So it should be allowed to be put on one line. And in languages whose
    syntax derives from C, you almost certainly can. (I can't think of any
    counter-examples, though that certainly doesn't prove they don't
    exist.) But the same thing is forced onto two lines in Python, and not
    for syntactic reasons - at least, not that I can see. Perhaps someone
    can enlighten me.

    Is there any fundamental reason that the syntax couldn't be expanded
    to permit "statement; statement" for any two given statements?

    ChrisA
    Chris Angelico, Oct 13, 2012
    #5
  6. Chris Angelico writes:

    > Here's a side challenge. In any shell you like, start with this
    > failing statement, and then fix it without retyping anything:
    >
    > sikorsky@sikorsky:~$ python -c "a=1; if a: print(a)"
    > File "<string>", line 1
    > a=1; if a: print(a)
    > ^
    > SyntaxError: invalid syntax
    >
    > In bash, I was unable to insert a newline into the quoted string. My
    > only option was to backspace everything after the point where I
    > wanted the newline, then hit enter, then retype the if. I'm curious
    > to know if that's simply because I didn't think of (some bash
    > feature), or alternatively, if there's another shell that would have
    > made this easy.


    C-v C-j inserts a newline for me, in bash.
    Jussi Piitulainen, Oct 13, 2012
    #6
  7. On Sun, Oct 14, 2012 at 4:43 AM, Jussi Piitulainen
    <> wrote:
    > Chris Angelico writes:
    >
    >> Here's a side challenge. In any shell you like, start with this
    >> failing statement, and then fix it without retyping anything:
    >>
    >> sikorsky@sikorsky:~$ python -c "a=1; if a: print(a)"

    >
    > C-v C-j inserts a newline for me, in bash.


    Ah! So it does. Thanks.

    *stashes that away in the "handy commands" index in his brain*

    ChrisA
    Chris Angelico, Oct 13, 2012
    #7
  8. On Sun, Oct 14, 2012 at 5:21 AM, Joshua Landau
    <> wrote:
    > Because Python uses indentation, what would "if A: print(1); if B: print(2)"
    > even do? It has to fail, because we have to assume consistent indentation
    > for ";"s*. With "\n" as I proposed, you still have to indent: it is just a
    > method to bypass lame shells [it would become "if A: print(1)\nif B:
    > print(2)"].


    sikorsky@sikorsky:~/cpython$ python -c "if False: print(1); print(2)"
    sikorsky@sikorsky:~/cpython$ python -c "if True: print(1); print(2)"
    1
    2
    sikorsky@sikorsky:~/cpython$

    The semicolon separates statements, but doesn't change nesting levels.
    The if statement increases the nesting level, which demands a
    corresponding indentation increase if you go onto a new line; the
    statement you describe is illegal because the 'if' isn't allowed to
    not be at the beginning of the line, but it's unambiguous.

    Of course, since Python lacks a non-whitespace way of indicating the
    end of an if block, there's no way to put your "if A" and "if B" onto
    the same line as peers. But that's a consequence of a design decision,
    and one that can't easily be changed. Every language has warts like
    that; eschewing variable declarations prevents infinite nesting of
    scopes, but demanding variable declarations makes interactive work
    harder. To paraphrase the Pirate King: Always follow the dictates of
    your conscience, and accept the consequences.

    ChrisA
    Chris Angelico, Oct 13, 2012
    #8
  9. On Sun, 14 Oct 2012 04:23:25 +1100, Chris Angelico <>
    declaimed the following in gmane.comp.python.general:

    > Back to the main point. In C-like languages, the newline is nothing
    > special. (ECMAScript allows the omission of semicolons at end of line
    > in many cases, but many style guides recommend using them anyway.) You


    That leads back to the Pascal even... The difference between a
    semi-colon as a statement terminator (Ada) and a statement separator
    (Pascal).

    --
    Wulfraed Dennis Lee Bieber AF6VN
    HTTP://wlfraed.home.netcom.com/
    Dennis Lee Bieber, Oct 13, 2012
    #9
  10. On Sun, 14 Oct 2012 05:41:11 +1100, Chris Angelico <>
    declaimed the following in gmane.comp.python.general:

    > On Sun, Oct 14, 2012 at 5:21 AM, Joshua Landau
    > <> wrote:
    > > Because Python uses indentation, what would "if A: print(1); if B: print(2)"
    > > even do? It has to fail, because we have to assume consistent indentation
    > > for ";"s*. With "\n" as I proposed, you still have to indent: it is just a
    > > method to bypass lame shells [it would become "if A: print(1)\nif B:
    > > print(2)"].

    >
    > sikorsky@sikorsky:~/cpython$ python -c "if False: print(1); print(2)"
    > sikorsky@sikorsky:~/cpython$ python -c "if True: print(1); print(2)"
    > 1
    > 2
    > sikorsky@sikorsky:~/cpython$
    >

    Which isn't the same example... The former would be:

    if False: print(1); if True: print(2)
    --
    Wulfraed Dennis Lee Bieber AF6VN
    HTTP://wlfraed.home.netcom.com/
    Dennis Lee Bieber, Oct 13, 2012
    #10
  11. On Sun, Oct 14, 2012 at 6:06 AM, Joshua Landau
    <> wrote:
    > The fact that your proposal can't allow "a=[]\nfor x in range(10):
    > a.append(x**a[-2])\nprint(a)" makes it somewhat an incomplete suggestion,
    > and code like:
    >
    >> while True: while True: break; break

    >
    > is just confusing.


    Agreed. However, I don't think there's going to be _any_ perfect
    solution for delimiting blocks, short of "from __future__ import
    braces".

    > I don't want to sound closed, but the options I'm really open to are:
    >
    > a) It does a limited set of things that make a those things nicer, á la"@"
    > b) It does almost everything, minus some carefully-chosen things deemed to
    > quirky, á la current newlines (which don't allow "if a: if b: pass")
    > c) It does everything that would be possible
    >
    > Your example falls nicely between a and b, which I do not find particularly
    > helpful. Mine attempts a by only applying to "python -c", but would be c if
    > it didn't. I find the syntax to horrible for general code, which is why I
    > didn't suggest that.
    >


    Your idea is an extension to the -c parameter that would technically
    work, but be fairly hard to manage in anything other than the trivial
    case. My idea is an extension to general syntax that would work in all
    cases where you aren't trying to put a statement after the end of what
    would be an indented block. Both have their limitations, but both
    would be - as far as I can see - backward compatible.

    ChrisA
    Chris Angelico, Oct 13, 2012
    #11
  12. On Sun, Oct 14, 2012 at 9:00 AM, Joshua Landau
    <> wrote:
    > That is also callable from the command-line like so:
    >>
    >> python -m debrace -c "if a: ${ print(1) $ print(2) $ while b: c() $ if g:
    >> ${ pass }$ }$ print(d)"


    Wait.... you're pretty much implementing from __future__ import braces?

    ChrisA
    Chris Angelico, Oct 13, 2012
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Shawn Minisall

    while within while

    Shawn Minisall, Oct 27, 2007, in forum: Python
    Replies:
    11
    Views:
    504
  2. Herman
    Replies:
    0
    Views:
    154
    Herman
    Oct 12, 2012
  3. Dave Angel
    Replies:
    0
    Views:
    181
    Dave Angel
    Oct 13, 2012
  4. Herman
    Replies:
    0
    Views:
    212
    Herman
    Oct 13, 2012
  5. Ned Deily
    Replies:
    0
    Views:
    170
    Ned Deily
    Oct 13, 2012
Loading...

Share This Page