Re: Multi-line commands with 'python -c'

2014-06-01 Thread Duncan Booth
Peter Otten __pete...@web.de wrote:

 Duncan Booth wrote:
 
 Chris Angelico ros...@gmail.com wrote:
 
 On Sat, May 31, 2014 at 7:42 AM, Devin Jeanpierre
jeanpierr...@gmail.com wrote:
 In unix shells you can literally use a new line. Or is that only
 bash?
 
 You can in bash, I know, but it's fiddly to type it; and more
 importantly, it's not a good point in the this is cleaner than a
 series of pipes argument. My primary recommendation, of course, was
 a three-line script saved as an actual file, but for a more direct
 parallel to the pipe-it-three-ways model, I wanted to use -c.
 
 and you also wrote originally that it's fiddly to edit. I think that
 Windows Powershell has (at least in the current ISE command line) got
 the editing a bit better. It's a minor difference though and it has
 taken Microsoft about 30 years to get to that point.
 
 What may be a larger difference, or may just be my lack of Linux-foo,
 is this:
 
 PS C:\python33 $script = @
 import os
 for root, dirs, files in os.walk(.):
 if len(dirs + files) == 1: print(root)
 @
 
 PS C:\python33 python -c $script
 .\Doc
 .\Lib\concurrent\__pycache__
 .\Lib\curses\__pycache__
 ...
 
 which is a style I've found useful for example when running a group
 of related timeit.py commands as I can put things like multi-line
 setup statements in a variable and then have a simpler command to
 repeat. 
 
 But bash as far as I can won't let me do that:
 
 $ script='import os
 for root, dirs, files in os.walk(.):
 if len(dirs + files) == 1: print(root)
 '
 $ python -c $script
   File string, line 1
 import
  ^
 SyntaxError: invalid syntax
  
 $ script='import os
 for root, dirs, files in os.walk(.):
 if len(dirs + files) == 1:
 print(root)
 '
 $ python3 -c $script
 .
 ./heureka
 
 $ python3 -c 'import sys; print(sys.argv)' $script
 ['-c', 'import', 'os', 'for', 'root,', 'dirs,', 'files', 'in', 
 'os.walk(.):', 'if', 'len(dirs', '+', 'files)', '==', '1:',
 'print(root)'] $ python3 -c 'import sys; print(sys.argv)' $script
 ['-c', 'import os\nfor root, dirs, files in os.walk(.):\nif
 len(dirs + files) == 1:\nprint(root)\n']
 
Thanks, I thought there must be a way to do that (and I should have 
remembered it). It nicely shows up the difference between the *nix 
shells that are all about processing the command line as a string and 
the Powershell way where it is all about objects (so a single value 
stays as a single argument).

-- 
Duncan Booth
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-31 Thread Duncan Booth
Chris Angelico ros...@gmail.com wrote:

 On Sat, May 31, 2014 at 7:42 AM, Devin Jeanpierre
jeanpierr...@gmail.com wrote:
 In unix shells you can literally use a new line. Or is that only 
bash?
 
 You can in bash, I know, but it's fiddly to type it; and more
 importantly, it's not a good point in the this is cleaner than a
 series of pipes argument. My primary recommendation, of course, was a
 three-line script saved as an actual file, but for a more direct
 parallel to the pipe-it-three-ways model, I wanted to use -c.

and you also wrote originally that it's fiddly to edit. I think that 
Windows Powershell has (at least in the current ISE command line) got 
the editing a bit better. It's a minor difference though and it has 
taken Microsoft about 30 years to get to that point.

What may be a larger difference, or may just be my lack of Linux-foo, is 
this:

PS C:\python33 $script = @
import os
for root, dirs, files in os.walk(.):
if len(dirs + files) == 1: print(root)
@

PS C:\python33 python -c $script
.\Doc
.\Lib\concurrent\__pycache__
.\Lib\curses\__pycache__
...

which is a style I've found useful for example when running a group of 
related timeit.py commands as I can put things like multi-line setup 
statements in a variable and then have a simpler command to repeat.

But bash as far as I can won't let me do that:

$ script='import os 
for root, dirs, files in os.walk(.):
if len(dirs + files) == 1: print(root)
'
$ python -c $script
  File string, line 1
import
 ^
SyntaxError: invalid syntax


-- 
Duncan Booth
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-31 Thread Peter Otten
Duncan Booth wrote:

 Chris Angelico ros...@gmail.com wrote:
 
 On Sat, May 31, 2014 at 7:42 AM, Devin Jeanpierre
jeanpierr...@gmail.com wrote:
 In unix shells you can literally use a new line. Or is that only
 bash?
 
 You can in bash, I know, but it's fiddly to type it; and more
 importantly, it's not a good point in the this is cleaner than a
 series of pipes argument. My primary recommendation, of course, was a
 three-line script saved as an actual file, but for a more direct
 parallel to the pipe-it-three-ways model, I wanted to use -c.
 
 and you also wrote originally that it's fiddly to edit. I think that
 Windows Powershell has (at least in the current ISE command line) got
 the editing a bit better. It's a minor difference though and it has
 taken Microsoft about 30 years to get to that point.
 
 What may be a larger difference, or may just be my lack of Linux-foo, is
 this:
 
 PS C:\python33 $script = @
 import os
 for root, dirs, files in os.walk(.):
 if len(dirs + files) == 1: print(root)
 @
 
 PS C:\python33 python -c $script
 .\Doc
 .\Lib\concurrent\__pycache__
 .\Lib\curses\__pycache__
 ...
 
 which is a style I've found useful for example when running a group of
 related timeit.py commands as I can put things like multi-line setup
 statements in a variable and then have a simpler command to repeat.
 
 But bash as far as I can won't let me do that:
 
 $ script='import os
 for root, dirs, files in os.walk(.):
 if len(dirs + files) == 1: print(root)
 '
 $ python -c $script
   File string, line 1
 import
  ^
 SyntaxError: invalid syntax
 
$ script='import os
 for root, dirs, files in os.walk(.):
 if len(dirs + files) == 1:
 print(root)
 '
$ python3 -c $script
.
./heureka

$ python3 -c 'import sys; print(sys.argv)' $script
['-c', 'import', 'os', 'for', 'root,', 'dirs,', 'files', 'in', 
'os.walk(.):', 'if', 'len(dirs', '+', 'files)', '==', '1:', 'print(root)']
$ python3 -c 'import sys; print(sys.argv)' $script
['-c', 'import os\nfor root, dirs, files in os.walk(.):\nif len(dirs + 
files) == 1:\nprint(root)\n']



-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-30 Thread Rustom Mody
On Friday, May 30, 2014 6:22:24 AM UTC+5:30, Chris Angelico wrote:
 Since lines are so critical to Python syntax, I'm a little surprised
 there's no majorly obvious solution to this... or maybe I'm just
 blind.

 Problem: Translate this into a shell one-liner:

 import os
 for root, dirs, files in os.walk(.):
 if len(dirs + files) == 1: print(root)

I would have thought this would work:

python -m os -c 'for root, dirs, files in os.walk(.): if len(dirs + files) == 
1: print(root)'

Unfortunately doesn't 
But did show up a small doc-bug:

This fact is not documented in 
$ man python
but is documented in 
$ python -h

Anyways...

I thought when one signs up for python one has to sign an affidavit
saying:
I shall not write one-liners\n * 100

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-30 Thread Rustom Mody
On Friday, May 30, 2014 11:34:36 AM UTC+5:30, Rustom Mody wrote:
 On Friday, May 30, 2014 6:22:24 AM UTC+5:30, Chris Angelico wrote:
  Since lines are so critical to Python syntax, I'm a little surprised
  there's no majorly obvious solution to this... or maybe I'm just
  blind.

  Problem: Translate this into a shell one-liner:


  import os
  for root, dirs, files in os.walk(.):
  if len(dirs + files) == 1: print(root)

Heres a (pr) approx

$ python -c 'import os, pprint; pprint.pprint ([ r for r, d, f in os.walk(.) 
if len(d+f) != 1])'


Mysterious that print after a ; is fine whereas for is not



 Anyways...

 I thought when one signs up for python one has to sign an affidavit
 saying:
 I shall not write one-liners\n * 100

I hope youve signed it by now wink
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-30 Thread Rustom Mody
On Friday, May 30, 2014 12:15:46 PM UTC+5:30, Rustom Mody wrote:
 Heres a (pr) approx
 
 $ python -c 'import os, pprint; pprint.pprint ([ r for r, d, f in 
 os.walk(.) if len(d+f) != 1])'

Without pprint: (pooor)

python -c 'import os; print \n.join([ r for r, d, f in os.walk(.) if 
len(d+f) != 1])'

Or (poor)

python -c 'from os import walk; print \n.join([ r for r, d, f in walk(.) if 
len(d+f) != 1])'
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-30 Thread Chris Angelico
On Fri, May 30, 2014 at 4:04 PM, Rustom Mody rustompm...@gmail.com wrote:
 I thought when one signs up for python one has to sign an affidavit
 saying:
 I shall not write one-liners\n * 100

Certainly not. I write all my list comps on one line!

*ducking for cover*

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-30 Thread Peter Otten
Rustom Mody wrote:

 On Friday, May 30, 2014 12:15:46 PM UTC+5:30, Rustom Mody wrote:
 Heres a (pr) approx
 
 $ python -c 'import os, pprint; pprint.pprint ([ r for r, d, f in
 os.walk(.) if len(d+f) != 1])'
 
 Without pprint: (pooor)
 
 python -c 'import os; print \n.join([ r for r, d, f in os.walk(.) if
 len(d+f) != 1])'
 
 Or (poor)
 
 python -c 'from os import walk; print \n.join([ r for r, d, f in
 walk(.) if len(d+f) != 1])'

If there are a lot of matching folders:

$ python -c 'import os, sys; sys.stdout.writelines(p + \n for p, f, n in 
os.walk(.) if len(n+f) == 1)'

With a little help from the shell:

$ echo -e import os\nfor p, f, n in os.walk('.'):\n if len(f+n) == 1: 
print(p) | python

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-30 Thread Rustom Mody
On Friday, May 30, 2014 12:50:31 PM UTC+5:30, Chris Angelico wrote:
 On Fri, May 30, 2014 at 4:04 PM, Rustom Mody wrote:
  I thought when one signs up for python one has to sign an affidavit
  saying:
  I shall not write one-liners\n * 100

 Certainly not. I write all my list comps on one line!

 *ducking for cover*

Heres a more vile misuse of python3's print-as-function + list-comp-as-for:

python3 -c 'from os import walk; [print(r) for r, d, f in walk(.) if len(d+f) 
== 1]'

Well if C programmers can use ',' as one-line ';' and '?:' as one-line if
why not python also?

[To noobs who are reading: Dont do this!]
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-30 Thread Chris Angelico
On Fri, May 30, 2014 at 10:47 PM, Rustom Mody rustompm...@gmail.com wrote:
 On Friday, May 30, 2014 12:50:31 PM UTC+5:30, Chris Angelico wrote:
 On Fri, May 30, 2014 at 4:04 PM, Rustom Mody wrote:
  I thought when one signs up for python one has to sign an affidavit
  saying:
  I shall not write one-liners\n * 100

 Certainly not. I write all my list comps on one line!

 *ducking for cover*

 Heres a more vile misuse of python3's print-as-function + list-comp-as-for:

 python3 -c 'from os import walk; [print(r) for r, d, f in walk(.) if 
 len(d+f) == 1]'

 Well if C programmers can use ',' as one-line ';' and '?:' as one-line if
 why not python also?

 [To noobs who are reading: Dont do this!]

I actually crafted the exact same vile misuse, prior to asking the question.

https://lists.debian.org/debian-user/2014/05/msg02019.html

Modulo trivialities like whitespace and the from-import, it's exactly
the same as your version.

Incidentally, C's ?: operator maps to Python's ternary if/else
operator, which most definitely is valid in a one-liner. So it's just
the semicolon that you're looking at. In C, you can combine any two
statements onto one line; in Python, certain statements may not follow
a semicolon. So it's not really ; and ?: that are the point here, but
that Python, with its stricter rules about newlines (as opposed to
any whitespace), doesn't seem to have a convenient notation for
putting multiple lines into a -c command.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-30 Thread Terry Reedy

On 5/30/2014 2:45 AM, Rustom Mody wrote:


$ python -c 'import os, pprint; pprint.pprint ([ r for r, d, f in os.walk(.) 
if len(d+f) != 1])'

Mysterious that print after a ; is fine whereas for is not


Not at all. Simple statememts can follow ; or :, compound statements cannot.

--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-30 Thread Duncan Booth
Chris Angelico ros...@gmail.com wrote:

 Problem: Translate this into a shell one-liner:
 
 import os
 for root, dirs, files in os.walk(.):
 if len(dirs + files) == 1: print(root)
 

This is one area where Windows seems to do better than Linux shells:

PS C:\python33 python -c import os`nfor root, dirs, files in os.walk('.'):`n  
  if len(dirs + files) == 1: print(root)`n
.\Doc
.\Lib\concurrent\__pycache__
.\Lib\curses\__pycache__
...

The `n shell escaped newline is interpreted well before Python runs.

Also the multiline version works and in Powershell ISE up-arrow pulls it back 
as a 
single unit for easy editing:

PS C:\python33 python -c @
import os
for root, dirs, files in os.walk('.'):
if len(dirs + files) == 1: print(root)
@
.\Doc
.\Lib\concurrent\__pycache__
.\Lib\curses\__pycache__
... and so on ...


-- 
Duncan Booth
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-30 Thread Devin Jeanpierre
In unix shells you can literally use a new line. Or is that only bash?

-- Devin

On Fri, May 30, 2014 at 2:11 PM, Duncan Booth
duncan.booth@invalid.invalid wrote:
 Chris Angelico ros...@gmail.com wrote:

 Problem: Translate this into a shell one-liner:

 import os
 for root, dirs, files in os.walk(.):
 if len(dirs + files) == 1: print(root)


 This is one area where Windows seems to do better than Linux shells:

 PS C:\python33 python -c import os`nfor root, dirs, files in 
 os.walk('.'):`nif len(dirs + files) == 1: print(root)`n
 .\Doc
 .\Lib\concurrent\__pycache__
 .\Lib\curses\__pycache__
 ...

 The `n shell escaped newline is interpreted well before Python runs.

 Also the multiline version works and in Powershell ISE up-arrow pulls it back 
 as a
 single unit for easy editing:

 PS C:\python33 python -c @
 import os
 for root, dirs, files in os.walk('.'):
 if len(dirs + files) == 1: print(root)
 @
 .\Doc
 .\Lib\concurrent\__pycache__
 .\Lib\curses\__pycache__
 ... and so on ...


 --
 Duncan Booth
 --
 https://mail.python.org/mailman/listinfo/python-list
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-30 Thread Chris Angelico
On Sat, May 31, 2014 at 7:42 AM, Devin Jeanpierre
jeanpierr...@gmail.com wrote:
 In unix shells you can literally use a new line. Or is that only bash?

You can in bash, I know, but it's fiddly to type it; and more
importantly, it's not a good point in the this is cleaner than a
series of pipes argument. My primary recommendation, of course, was a
three-line script saved as an actual file, but for a more direct
parallel to the pipe-it-three-ways model, I wanted to use -c.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Multi-line commands with 'python -c'

2014-05-29 Thread Chris Angelico
Since lines are so critical to Python syntax, I'm a little surprised
there's no majorly obvious solution to this... or maybe I'm just
blind.

Problem: Translate this into a shell one-liner:

import os
for root, dirs, files in os.walk(.):
if len(dirs + files) == 1: print(root)

Solution 1: SyntaxError

python -c 'import os; for root, dirs, files in os.walk(.): if
len(dirs + files) == 1: print(root)'

You can't put a 'for' statement after an 'import' with just a semicolon.

Solution 2: SyntaxError

python -c 'import os\nfor root, dirs, files in os.walk(.): if
len(dirs + files) == 1: print(root)'

You can't put a backslash escape into your code like that! Makes no sense.

Solution 3: Silence

python -c 'import os' -c 'for root, dirs, files in os.walk(.): if
len(dirs + files) == 1: print(root)'

Haven't dug into exactly what this does, but the docs say that -c
terminates the option list, so I would guess that the second -c and
its arg get passed to the script.

Solution 4: Rely on the shell's ability to pass newlines inside arguments

$ python -c 'import os
 for root, dirs, files in os.walk(.):
 if len(dirs + files) == 1: print(root)
 '

That works, but at that point, you aren't writing a one-liner any
more. It's also fiddly to edit.

Is there a better way to put multiple virtual lines into a 'python -c' command?

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Multi-line commands with 'python -c'

2014-05-29 Thread Zachary Ware
On Thursday, May 29, 2014, Chris Angelico ros...@gmail.com
javascript:_e(%7B%7D,'cvml','ros...@gmail.com'); wrote:

 Since lines are so critical to Python syntax, I'm a little surprised
 there's no majorly obvious solution to this... or maybe I'm just
 blind.

 Problem: Translate this into a shell one-liner:

 import os
 for root, dirs, files in os.walk(.):
 if len(dirs + files) == 1: print(root)

snip


 Is there a better way to put multiple virtual lines into a 'python -c'
 command?


You can always cheat:

$ python -c 'exec(import os\nfor root, dirs, files in os.walk(\.\):\n if
len(dirs + files) == 1: print(root))'

Doesn't do much for being long and fiddly, though.

--
Zach

Sent from an iPad, please bear with any brevity, uncaught
auto-uncorrections, HTML, or other annoyances. Suggestions for a great (not
just 'good') email app are welcome.


-- 
Sent from Gmail Mobile
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multi-line commands with 'python -c'

2014-05-29 Thread Chris Angelico
On Fri, May 30, 2014 at 12:34 PM, Zachary Ware
zachary.ware+pyl...@gmail.com wrote:
 You can always cheat:

 $ python -c 'exec(import os\nfor root, dirs, files in os.walk(\.\):\n if
 len(dirs + files) == 1: print(root))'

 Doesn't do much for being long and fiddly, though.

Not really, no! Heh. I wrote that in competition against a theoretical
solution involving shell commands and pipes and so on, with the
intention being that the Python version could be a simple shell
one-liner, just as the pipe version could. (The task: Find all
directories with exactly one subdirectory or file in them, not
counting dot and dot-dot. Python's os.walk() is pretty much perfect
for that.) I tried fiddling with __import__() rather than the import
statement, but it didn't really aid clarity much.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list