Bash script loop on python variable - python

I'm trying to do a simple script, but I don't get how to pass a variable to the command that I need:
#!/bin/bash
for i in 1 2 3
do
python -c 'print "a"*' $i
done

If you really want to go on with your solution using python -c, you would have to remove the space:
#!/bin/bash
for i in 1 2 3
do
python -c 'print "a"*'$i
done
But the approach suggested by Asmox makes more sense to me (and it has nothing to do with the question where you pipe the standard output to).

Maybe this topic will help:
How do I run Python script using arguments in windows command line
Have you considered making a whole script? Like this one:
import sys
def f(a):
print a
if __name__ == "__main__":
a = int(sys.argv[1])
f(a)
This example might seem overcomplicated, but I wanted to show you how to pass parameter from console to function

I have tried the solution provided above and had to modify for python3+
due to lack of sufficient points I am not allowed to make a comment, thats why I posted my solution separately
#!/bin/bash
for i in {1..3}
do
python -c "print ('a'* ${i})"
done
output~>
a
aa
aaa

Related

Passing arguments to cell magic %%script

Closest related question is this one: In Ipython, how can I pass arguments to a cell as though it were its own script?
I am writing an ipython notebook to make simulations and then create an animation in paraview. The way I do this is run a cell with the magic command
%%script pvpython
since paraview has its own interpreter. The problem is that I need it to pass it the directory of the vtu files as an argument (which are a variable in the IPython kernel). So far I have been unable to figure this out. I have tried:
%%script pvpython path/to/files
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('foo')
args = parser.parse_args()
print(args.foo)
But this gives an error: `Got unknown argument: path/to/files because the argument is being passed to the magic command not the python script. Is there a way to get around this?
Edit: This is different from the linked question because I am using a cell magic not line magic. I would prefer to have all my code visible in the notebook alone.
I don't exactly recall where I found this, and it doesn't seem to be documented, but this is an extremely useful feature for cell magics.
This isn't a python formatting mechanism, it's the same jupyter interpolation used for interpolation in line magics starting with !. Note the absence of quotes in the carelessly-quoted variable.
Cell 1:
simple_var = 123
crazy_var = " with spaces \n 'asdf' $DOLLAR$$ $$SIGNS$$ "
import shlex
tamed_var = shlex.quote(crazy_var)
Cell 2:
%%bash -s '{simple_var}' {tamed_var} '{crazy_var}'
echo $#
for i in $(seq 1 $#) ; do
echo "$i: ${!i}"
done
Cell 2 output:
3
1: 123
2: with spaces
'asdf' $DOLLAR$$ $$SIGNS$$
3: with spaces
asdf $DOLLAR$$ $$SIGNS$$
As an aside, the script form is also a convenient way of timing bash cells: %%script time bash -s '{simple_var}' {tamed_var} '{crazy_var}' would be the replacement above.
The docs are here, but they don't go deep into what %%script does. Based on this behavior, though, it looks like jupyter feeds the rest of the cell as standard input. This is interesting, since it says "%%script is basically shebang", which is not the case (otherwise we wouldn't need bash's -s). So in your case you replace the bash -s magic I used above with script pvpython.

Pass a code of Python in a command line

Is it possible to somehow convert string which I pass via command line e.g
python myfile.py "s = list(range(1000))"
into module? And then...
#myfile.py
def printlist(s):
print(s)
?
Something like a timeit module, but with my own code.
python -m timeit -s "s = list(range(1000))" "sorted(s)"
Save the code
import sys
print(sys.argv)
as filename.py, then run python filename.py Hi there! and see what happens ;)
I'm not sure if I understand correctly, but the sys module has the attribute argv that is a list of all the arguments passed in the command line.
test.py:
#!/usr/bin/env python
import sys
for argument in sys.argv:
print(argument)
This example will print every argument passed to the script, take in mind that the first element sys.argv[0] will always be the name of the script.
$ ./test.py hello there
./test.py
hello
there
There are two options to send short code snippets similar to what you can do via the timeit module or certain other -m module option functionality and these are:
You can use either the -c option of Python e.g.:
python -c "<code here>"
Or you could use piping such as:
echo <code here> | python
You can combine multiple statements using the ; semicolon statement separator. However if you use a : such as with while or for or def or if then you cannot use the ; so there may be limited options. Possibly some clever ways around this limitation but I have yet to see them.

How to insert a python program into a bash script?

I have a small python program that parses a text file and writes the output to another file. Currently, I am writing a bash script to call this program several times, it looks something like:
for i in $(seq 1 100); do
python /home/Documents/myProgram.py myTextFile$i
done
This works fine but I want to know if it is possible to have the python program inside the bash script file so when another user runs the script they don't need to have the python program in their memory; i.e., is it possible to copy and paste the python program into the bash script and run it from within the script itself?
#!/bin/bash
python - 1 2 3 << 'EOF'
import sys
print 'Argument List:', str(sys.argv)
EOF
Output:
Argument List: ['-', '1', '2', '3']
I think you should be able to put:
python << END
[Python code here]
END
But I have not tested this.
for simple scripts you can also run python with the -c option. For example
python -c "x=1; print x; print 'great program eh'"
I wouldn't recommend writing anything too complicated, but it could work for something simple.
Pardon the thread necromancy, but here's a technique that is missing that may be useful to someone.
#!/bin/bash
""":" # Hide bash from python
for i in $(seq 1 100); do
python3 $(readlink -f "$0") myTextFile$i
done
exit
"""
# Python script starts here
import sys
print('Argument List: ', str(sys.argv))
However, I do agree with the general recommendation to just do the loop in Python.

Python script argument conditional

Is anyone able to tell me how to write a conditional for an argument on a python script? I want it to print "Argument2 Entered" if it is run with a second command line arguments such as:
python script.py argument1 argument2
And print "No second argument" if it is run without command line arguments, like this:
python script.py argument1
Is this possible?
import sys
if len(sys.argv)==2: # first entry in sys.argv is script itself...
print "No second argument"
elif len(sys.argv)==3:
print "Second argument"
There are many answers to this, depending on what exactly you want to do and how much flexibility you are likely to need.
The simplest solution is to examine the variable sys.argv, which is a list containing all of the command-line arguments. (It also contains the name of the script as the first element.) To do this, simply look at len(sys.argv) and change behaviour based on its value.
However, this is often not flexible enough for what people expect command-line programs to do. For example, if you want a flag (-i, --no-defaults, ...) then it's not obvious how to write one with just sys.argv. Likewise for arguments (--dest-dir="downloads"). There are therefore many modules people have written to simplify this sort of argument parsing.
The built-in solution is argparse, which is powerful and pretty easy-to-use but not particularly concise.
A clever solution is plac, which inspects the signature of the main function to try to deduce what the command-line arguments should be.
There are many ways to do this simple thing in Python. If you are interested to know more than I recommend to read this article. BTW I am giving you one solution below:
import click
'''
Prerequisite: # python -m pip install click
run: python main.py ttt yyy
'''
#click.command(context_settings=dict(ignore_unknown_options=True))
#click.argument("argument1")
#click.argument("argument2")
def main(argument1, argument2):
print(f"argument1={argument1} and argument2={argument2}")
if __name__ == '__main__':
main()
Following block should be self explanatory
$ ./first.py second third 4th 5th
5
$ cat first.py
#!/usr/bin/env python
import sys
print (len(sys.argv))
This is related to many other posts depending upon where you are going with this, so I'll put four here:
What's the best way to grab/parse command line arguments passed to a Python script?
Implementing a "[command] [action] [parameter]" style command-line interfaces?
How can I process command line arguments in Python?
How do I format positional argument help using Python's optparse?
But the direct answer to your question from the Python docs:
sys.argv -
The list of command line arguments passed to a Python script. argv[0] is the script name (it is operating system dependent whether this is a full pathname or not). If the command was executed using the -c command line option to the interpreter, argv[0] is set to the string '-c'. If no script name was passed to the Python interpreter, argv[0] is the empty string.
To loop over the standard input, or the list of files given on the command line, see the fileinput module.

I want to have raw_input and nohup together in python

I am dealing with a large data set and it takes some days to run, therefore I use nohup to run my script in terminal.
This time I need to first get a raw_input from terminal then by nohup, my codes starts running. Any suggestion how I can do that?
so first I need to get input from terminal like this
$ python myprogram.py
enter_input: SOMETHING
then the process should be like this:
$nohup python myprogram.py &
But I want to do this in one step via terminal. I hope my explanation is clear :)
Here's one more option, in case you want to stick with the user-friendly nature of the input box. I did something like this because I needed a password field, and didn't want the user to have to display their password in the terminal. As described here, you can create a small wrapper shell script with input boxes (with or without the -s option to hide), and then pass those variables via the sys.argv solution above. Something like this, saved in an executable my_program.sh:
echo enter_input:
read input
echo enter_password:
read -s password
nohup python myprogram.py $username $password &
Now, running ./my_program.sh will behave exactly like your original python my_program.py
I think you shouldn't your program have read input from stdin, but give it data via its command line.
So instead of
startdata = raw_input('enter_input:')
you do
import sys
startdata = sys.argv[1]
and you start your program with
$ nohup python myprogram.py SOMETHING &
and all works the way you want - if I get you right.
You could make your process fork to the background after reading the input. The by far easier variant, though, is to start your process inside tmux or GNU screen.

Categories