Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Embedding Python in a shell script

60 views
Skip to first unread message

Jason Friedman

unread,
Jun 16, 2011, 8:57:25 PM6/16/11
to pytho...@python.org
$ cat test.sh
#!/bin/bash
for i in 1 2 3 4; do
python -c "
for j in range($i):
print j
"
done

$ sh test.sh
0
0
1
0
1
2
0
1
2
3

The code behaves as I expect and want, but the de-denting of the
Python call is unattractive, especially unattractive the longer the
Python call becomes. I'd prefer something like:

$ cat test.sh
#!/bin/bash
for i in 1 2 3 4; do
python -c "
for j in range($i):
print j
"
done

But that yields:

$ sh test.sh
File "<string>", line 2
for j in range(1):
^
IndentationError: unexpected indent
File "<string>", line 2
for j in range(2):
^
IndentationError: unexpected indent
File "<string>", line 2
for j in range(3):
^
IndentationError: unexpected indent
File "<string>", line 2
for j in range(4):
^
IndentationError: unexpected indent

I realize I can create a "call_me.py" and do:

$ cat test.sh
#!/bin/bash
for i in 1 2 3 4; do
python call_me.py $i
done

but for various reasons I want a single script. Any alternatives?

Chris Angelico

unread,
Jun 16, 2011, 9:05:46 PM6/16/11
to pytho...@python.org
On Fri, Jun 17, 2011 at 10:57 AM, Jason Friedman <ja...@powerpull.net> wrote:
> The code behaves as I expect and want, but the de-denting of the
> Python call is unattractive, especially unattractive the longer the
> Python call becomes.  I'd prefer something like:
>

#!/bin/bash


for i in 1 2 3 4; do

python -c "if True:


for j in range($i):
print j
"
done

Untested, but it's a hack I've used in a few places. The if tells
Python to expect an indent, and nobody cares if your first indent is
two miles and the one after that is only another two spaces.

ChrisA

rusi

unread,
Jun 16, 2011, 10:25:56 PM6/16/11
to
On Jun 17, 6:05 am, Chris Angelico <ros...@gmail.com> wrote:

> > Python call becomes.  I'd prefer something like:
>
> #!/bin/bash
> for i in 1 2 3 4; do
>   python -c "if True:

# comfortably indented python code

Thanks. Nice!

mg

unread,
Jun 17, 2011, 4:58:37 AM6/17/11
to
rusi <rusto...@gmail.com> wrote:
> On Jun 17, 6:05ᅵam, Chris Angelico <ros...@gmail.com> wrote:
>
>> > Python call becomes. ᅵI'd prefer something like:

>>
>> #!/bin/bash
>> for i in 1 2 3 4; do
>> ᅵ python -c "if True:

> # comfortably indented python code
>
> Thanks. Nice!

You can use bash here document feature, <<-, that strips heading tab
characters but not spaces.


#!/bin/bash

for i in 1 2 3 4; do

python /dev/stdin <<-EOF
for i in range($i):
print i # two tabs and four spaces
EOF
done

Or alternatively you can use a temporary file:


#!/bin/bash

TEMPFILE=$(mktemp)
trap 'rm -f $TEMPFILE' TERM INT

cat > $TEMPFILE <<EOF
import sys

for i in range(int(sys.argv[1])):
print i
EOF

for i in 1 2 3 4; do

python $TEMPFILE $i
done


Timo Lindemann

unread,
Jun 17, 2011, 1:47:50 PM6/17/11
to
On Fri, 17 Jun 2011 00:57:25 +0000, Jason Friedman said:


>
> but for various reasons I want a single script. Any alternatives?

you can use a here document like this:


#! /bin/bash

/usr/bin/python2 << EOPYTHON
def hello():
print("Hello, World");

if __name__ == "__main__":
hello();

EOPYTHON

Hans Mulder

unread,
Jun 17, 2011, 4:15:57 PM6/17/11
to

That does not solve the problem as stated. The OP wants to call python
inside a loop and he wants to indent things properly:

#!/bin/bash

for i in 1 2 3 4 5
do
python << EOPYTHON


def hello():
print("Hello, World");

if __name__ == "__main__":
hello();
EOPYTHON

done

That doesn't work, because the EOPYTHON token is indented.

If you put the EOPYTHON token flush left, it still doesn't work, because
Python does not accept indentation on line 1:

File "<stdin>", line 1
def hello():
^
IndentationError: unexpected indent


For some ideas that may work, read the earlier posts in this thread.


-- HansM

Timo Lindemann

unread,
Jun 17, 2011, 4:43:13 PM6/17/11
to
On Fri, 17 Jun 2011 22:15:57 +0200, Hans Mulder said:

> On 17/06/11 19:47:50, Timo Lindemann wrote:
>> On Fri, 17 Jun 2011 00:57:25 +0000, Jason Friedman said:
>>
>>
>>
>>> but for various reasons I want a single script. Any alternatives?
>>
>> you can use a here document like this:

> That does not solve the problem as stated. The OP wants to call python
> inside a loop and he wants to indent things properly:

so, wrap it inside a bash function like this:

#! /bin/bash

call_python() {
/usr/bin/python2 << EOPYTHON
def hello():
print("Hello, World $1");

if __name__ == "__main__":
hello();

EOPYTHON
}

for i in 1 2 3 4 5 6
do
call_python $i
done

That way, the indentation on is nicer; passing parameters to the script
inside the heredoc might be mean if the parameters are formed
difficultly, like, causing syntax errors if it's something like '"' or
somesuch. Probably beside the point though.

> For some ideas that may work, read the earlier posts in this thread.

maybe my news server doesn't fetch the whole thread. I didnt see any
replies, and still don't except yours.

Nice evenin'
-T.

Jason Friedman

unread,
Jun 18, 2011, 1:13:18 AM6/18/11
to pytho...@python.org
Thank you, everyone, for your suggestions. I'll try them all and
decide which I like best.
0 new messages