Execute multi-line python code inside Windows Batch script - python

I want to use multiline python statements inside Windows Batch script.
For example, my BAT script is:
#echo off
echo "Executing Python Code..."
goto python_code
:python_code_back
echo "Executed Python Code!"
pause
exit()
:python_code
python -c print("""Python code running""")
goto python_code_back
python -c works fine for single statements. But let my python code be embedded is:
import random
num = input("Enter Number: ")
num = int(num)
if num%2 == 0:
print("Even")
else:
print("Odd")
exit()
How do I embed this Python code into my Windows Batch Script without calling another python script or making temporary python files?
I have some options that I have gone through:
Use python -c with semicolons: How do I intend the code like if
statements above? If there are ways, one might still want clean code
in multiple lines but I would appreciate the answer for this.
Can I just run python and find a way to send commands to the interpreter? Maybe using subprocesses?
Is there any way I can build a multi-line string that has the python code and then send it to the python interpreter or python command?
In bash we could use EOF to keep multi-lines clean. Is there any similar method to this in BAT? I think no because people have proposed many workarounds to this.
Can ''' (three single-quotes) or """ (three douuble-quotes) syntax be used that are specially interpreted by Batch? Like here?

Try like this:
0<0# : ^
'''
#echo off
echo batch code
python %~f0 %*
exit /b 0
'''
import random
import sys
def isOdd():
print("python code")
num = input("Enter Number: ")
num = int(num)
if num%2 == 0:
print("Even")
else:
print("Odd")
def printScriptName():
print(sys.modules['__main__'].__file__)
eval(sys.argv[1] + '()')
exit()
Example usage:
call pythonEmbeddedInBatch.bat isOdd
call pythonEmbeddedInBatch.bat printScriptName
The first line will be boolean expression in python ,but a redirection to an empty label in batch. The rest of the batch code will be within multiline python comment.

Related

Output of interactive python to shell variable

There is an interactive python script something like
def myfunc():
print("enter value between 1 to 10")
i=int(input())
if(i<1 or i>10):
print("again")
myfunc()
else:
print(i)
I want to store the final output which is print(i) in a shell variable. Something like
python myFile.py | read a
Above query get stuck everytime i run the command. Is it possible to do that?
Even though ( read b | python myFile.py ) | read a defeats the purpose of interactive python function but this doesn't work as well. It works if myfunc() is non-interactive(not expecting user input). The function in reality takes some input, manipulates it, and then output the result in required format. I know it would be much easier to use either python or shell, but since i already wrote the python function, was wondering if it is possible to link both. If yes, is it also possible to add only final value to shell variable rather than all the print()
Same issue happens(terminal gets stuck) when i do
python myFile.py > someFilename
However file someFilename was created even though terminal was unresponsive. It seems shell is starting both the processes at the same time which makes sense. I am guessing if somehow python myfile.py executes independently before opening the pipe it could be possible, but i may be wrong.
If you are working on Linux or other Unix variants, would you please try:
import os
def myfunc():
tty = os.open("/dev/tty", os.O_WRONLY)
os.write(tty, "enter value between 1 to 10\n")
i=int(input())
if(i<1 or i>10):
os.write(tty, "again\n")
myfunc()
else:
print(i)
BTW if your shell is bash, it will be better to say:
read a < <(python myFile.py)
Otherwise read a is invoked in the subshell and the variable a
cannot be referred in the following codes.

How to create a shell program that accepts commands and prints a "$" prompt to indicate that a user can input a command using a while loop?

I'm a beginner Python coder and I'm very unsure on how to create a simple shell program that accepts commands (ex. printrecipes, printinventory, load etc.)
The input should look like:
$ loadrecipes
$ printmoney()
20
For this shell, I'm trying to use a while loop so it continues through the program without crashing even if they input a command that is acceptable.
def handle_commands():
keep_going=True
command=input("$" + " ")
while keep_going:
if command == '$ quit':
keep_going = False
break
elif command == "$ loadrecipefile(recipe_file)"
j
elif command == "$ printrecipes":
printrecipes()
elif command == "$ printiinventory":
printiinventory()
elif command == "$ printmoney":
printmoney()
elif command == "$ buyingredient":
I have no idea what to go from here.
The commands are that loadrecipes(recipe_file) takes in one argument, all print commands don't take an argument, buyingredient(ingredient_name, number:int) takes in 2 arguments (the ingredient name and how many of those ingredients).
So, for each command I have created a function in correspondence. Such as for printiinventory() I have:
def printiinventory():
print(iinventory['apple'],iinventory['beets'],iinventory['carrots'])
so if the command is:
$ printiinventory
0 4 3
it should come out to be like this
So your flow should look like this:
while True:
command = input("$ ")
if command is ...
elif ...:
Very similar to what you have, with the difference that you don't need to expect $ into the user's input. Input function prints the argument passed and returns SOLELY the user's input, not the rest of the content in the same line. So you should check for commands like command == "printrecipes", etc.
Explanation:
This piece of code:
x = input(str)
Is equivalent to:
print(str); x = input(str)
with the only difference that print() creates a new line, so the input will be taken from the line just below the printed content.
You could emulate this behaviour (the printing in the same line, that is) with the IO low-level Python modules, but there is no need when you can do just that.
Edit
In order to parse the commands, you can opt for the classical command line interface syntax, that separates command name and argument with spaces, or you could make your own parser. In case you go for the first, you could use Python's built-in argparse module. In case you'd rather use the second (which is more of a headache, especially if you are a starter), you have to write your own parser from scratch. Is not that big of a deal if you know regex, but I'm afraid that's a different question you should ask in the site. I would recommend you to take a look at some tutorials. Just googling: "make my own command parser python" gives you thousands of results, even though most of them will go for classic command line parsing syntax.
Edit 2
I've noticed you use some sort of flag to check if you need to keep going inside the loop. That is useless in the piece of code you use; just use break command and you're good to go.
Edit 3
Taking a close look at the OP's comments, I see you are trying to write Python code to be executed by a Python script. You can for sure do that; you've got the eval and exec modules, BUT note that this is a very risky practice, code can very easily be injected into your program, causing huge security holes. It is highly discouraged to do that. You have to separate command parsing from task executing. The user cannot ever have direct access to the control flow of the program.

How to execute multiline python code from a bash script?

I need to extend a shell script (bash). As I am much more familiar with python I want to do this by writing some lines of python code which depends on variables from the shell script. Adding an extra python file is not an option.
result=`python -c "import stuff; print('all $code in one very long line')"`
is not very readable.
I would prefer to specify my python code as a multiline string and then execute it.
Use a here-doc:
result=$(python <<EOF
import stuff
print('all $code in one very long line')
EOF
)
Tanks to this SO answer I found the answer myself:
#!/bin/bash
# some bash code
END_VALUE=10
PYTHON_CODE=$(cat <<END
# python code starts here
import math
for i in range($END_VALUE):
print(i, math.sqrt(i))
# python code ends here
END
)
# use the
res="$(python3 -c "$PYTHON_CODE")"
# continue with bash code
echo "$res"

Changing BASH script to Python

I am trying to convert this script to Python but am having problems with the BASH syntax ${variable}. This does something I do not understand as I have very little experience with BASH scripting. My question is basically,how can I do the dollar brackets variable thing in Python ${variable}. In my case the variable is a number from zero to two-hundred and fifty-five. Please see the BASH script below. I am trying to do the exact same thing in Python.
do
for code in {0..255};
do echo -e "\e[38;05;${code}m $code: Test";
done;
done
Here is my attempt to convert the code to a Python script. Unfortunately, I am still having to call BASH via the os.system() method or function. Please check out my script below. The script does not function the same way though, with changing the text in the BASH shell. The Python script below simply prints out the crazy text below and increments the numbers... :/
#! /usr/bin/env python
import os
def run():
for code in range(0, 255):
os.system('echo -e "\e[38;05;%dm %s Test"' % (code,str(code)))
run()
You can use print command and string formatting to evaluate your variable during the print.
BTW, you can use xrange rather than range in order not to generate all the numbers in your memory, but to yield it one-by-one (for large range)
You can use this:
import os
def run():
for code in range(0, 256):
print "\x1b[38;05;{code}m {code} Test".format(code=code)
run()
You’ll need to use string formatting.
Strangely enough, you already do this in your code (but using the old % syntax instead of the new .format method). I’m not even sure why you think you have to call echo since the string you pass to it is already the string that you are trying to get (if I understand your question right). Just use the print function to output the string.
try this:
#! /usr/bin/env python
import os
def run():
for code in range(0, 255):
os.system('/bin/echo -e "\e[38;05;%dm %s Test"' % (code,str(code)))
run()
the echo is usually both extrnal program and internal command of shell, which can make difference sometime

python program behaves differently in python shell vs terminal

I have a simple Python program that asks yes or no question and I validate that input.
If I run this Python shell, it runs fine. If I enter invalid characters it loops back to top of while.
However, if I run this in the terminal window and try to enter an invalid character it errors as shown below.
endProgram = 0
while endProgram != 1:
userInput = input("Yes or No? ");
userInput = userInput.lower();
while userInput not in ['yes', 'no']:
print("Try again.")
break
endProgram = userInput == 'no'
Looks like your RPi is using Python 2; the input function does an eval there.
input in Python 3 is equivalent to raw_input in Python 2. (See PEP-3111)
Ideally, you should change your RPi interpreter to Python 3. Failing that, you can make it version-agnostic like so:
try:
input = raw_input
except NameError:
pass
I can clearly see in the interactive shell you working in python 3.2.3 (background). But I can not see the python version you're running from the command line (foreground).
On your raspberrypi, execute this command from the shell:
python --version
I am expecting to see python 2.x here, because the behaviour of input() differs between python 2 and python 3, in a way that would cause exactly the behaviour you have seen.
You might want to add a line like
#!/usr/bin/env python3
To the top of your .py file, and then chmod +x on it. Afterward you should be able to execute it directly (./guipy01.py) and the correct python interpreter will be selected automatically.

Categories

Resources