'Get user input for a Python script ran from a bash script

Tldr at the end

I have a simple Python script with a few functions, let's give this main.py as a minimal example :

import sys

def userAdd():
        var = input("Please type any input: ")
        print("My input is", var)

if __name__ == '__main__':
    globals()[sys.argv[1]]()

When I call :

python main.py userAdd

Everything works fine. The script runs, the Python console asks me for my input, and then edits the JSON file. Now I want this script to be executed everytime I edit a text file, let's say myfile.txt which for now only has this line :

foo

For this, I use this bash script and changed the "RUN COMMAND" line with python main.py userAdd (let's call it update.sh):

#!/bin/bash

### Set initial time of file
LTIME=`stat -c %Z ./myfile.txt`

while true
do
   ATIME=`stat -c %Z ./myfile.txt`

   if [[ "$ATIME" != "$LTIME" ]]
   then
       python main.py userAdd
       LTIME=$ATIME
   fi
   sleep 1
done

My problem happens here. Everytime the Python script is called from the Bash script, the input prompt shows up. I enter a value, and I get a bash : <input> command not found, which means the current tty I'm using isn't Python, but Bash

$ chmod +x update.sh
$ ./update.sh &
$ echo "bar" >> myfile.txt
$ Please type any input: test
bash: test : command not found

I tried a few things (using /usr/bin/env and /dev/tty or <&1, or using python -i).

tldr; My Python script asks for a user input to update a file. When I run it directly from my bash terminal (python main.py myfunction), it works fine. When I run this Python script from a Bash script (which contains this same python [...] line) and type my input, I get a bash <input> command not found. This means that the terminal isn't Python's but Bash's. How can I get a Python terminal which will accept my input in this case ?



Solution 1:[1]

For anyone who might be facing the same issue, here's how I solved it : I edited the line from update.sh invoking the Python script like so :

#!/bin/bash

### Set initial time of file
LTIME=`stat -c %s ./myfile.txt`

while true
do
   ATIME=`stat -c %s ./myfile.txt`
   if [[ "$ATIME" >= "$LTIME" ]]
   then
       /usr/bin/konsole -e /usr/bin/bash -c './main.py userAdd'
       LTIME=$ATIME
   fi
   sleep 1
done

So this line ties me up to a specific terminal, but I think this could easily be bypassed by more advanced Linux users.

Then, when I run the script using ./update.sh & and add this line to a cron, everytime I edit and close the file, a new terminal runs, asks for the input prints the results then closes (although for the sake of the example a wait() command should be added after the print()).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Emmanuel Daveau