I want to have raw_input and nohup together in python - 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.

Related

Why Does Python Call a Subprocess Command Incorrectly?

This is a follow up on a previous question as I have made progress(which is irrelevant at this point). It is worth noting that I am learning python and barely know what I am doing, however, I am familiar with programming. I am trying to call an SCP command in the windows terminal through python. However, it is not doing the desired effect. The script runs smoothly with no errors and it prints the debug commands as I have written them. However, the SCP call does not actually go through on the other end. To make sure I have the right command, I have it set to print the same command that it called afterwards. When I copy this printed command and paste it into the windows command terminal, it gives the desired effect. Why is the same command not working correctly in python? Thanks. This is my script:
import subprocess
subprocess.run(['scp', 'c:/users/<name>/desktop/OOGA.txt', 'pi#<IP>:here/'], shell=True)
print ("done")
print ('scp', 'c:/users/<name>/desktop/OOGA.txt', 'pi#<IP>:here/')
Try using raw string if shell is set to True:
from subprocess import run as subrun
status = subrun(r'scp c:/users/<name>/desktop/OOGA.txt pi#<IP>:here/',shell=True)
print("Done")
print(status)

Python curses does not work with command substitution

I was using python project pick to select an option from a list. Below code returns the option and index.
option, index = pick(options, title)
Pick uses curses library from python. I want to pass the output of my python script to shell script.
variable output = $(pythonfile.py)
but it gets stuck on the curses screen. It cannot draw anything. What can be the reason for this?
pick gets stuck because when you use $(pythonfile.py), the shell redirects the output of pythonfile.py as if it were a pipe. Also, the output of pick contains characters for updating the screen (not what you want). You can work around those problems by
redirecting the output of pythonfile.py to /dev/tty
ensuring that your pythonfile.py writes its result to the standard error, and
directing the standard error in the shell script to the output of the $(...) construct.
For example:
#!/bin/bash
foo=$(python basic.py 2>&1 >/dev/tty )
echo "result '$foo'"
and in pythonfile.py, doing
import sys
print(option, index, file=sys.stderr)
rather than
print(option, index)
To pass the output of a Python script to a Bash variable you need to specify the command with which to open the python file inside the variable's declaration.
Like so:
variable_output=$(python pythonfile.py)
Furthermore, if you'd like to pass a variable from Python to bash you could use Python's sys module and then redirect the stderr.
Like so:
test.py
import sys
test_var = (str(3 + 3))
sys.exit(test_var)
test.sh
test_var=$(python3 test.py 2>&1)
echo $testvar
Now, if we run test.sh we get the output 6.

Execute multiple shell/command prompt commands in same instance

I am looking for a way to execute multiple commands in the same shell instance using a separate function for each, something that I can define when the shell process opens/closes and can pass commands to.
so far all the answers I have found have only been in a single function
ie:
#!/usr/bin/env python
from subprocess import check_call
check_call(r"""set -e
ls -l
<some command> # This will change the present working directory
launchMyApp""", shell=True)
I need the same effect but with each command in a different function like
shell.open()
shell.exec("dir")
shell.exec("cd C:/Users/" + User + "/Desktop)
shell.close()
if you are wondering whyyy it has to be separate the command to run is coming from user input. yes I realize that is a security risk, but security isn't a problem in this case, as its purely an educational venture and not going to be used for anything
you could use subprocess.check_call(cmds_str, shell=True) in conjunction with multiple commands in the same line: How to run two commands in one line in Windows CMD?
You could build each command individually and add them to a list, and then use ' & '.join(cmd_list) to get cmds_str.
I don't use Windows but it works on Linux.
You can try pexpect with cmd.exe
import pexpect
child = pexpect.spawn("cmd.exe")
child.expect_exact("> ")
#print(child.before.decode('utf-8'))
print(child.before)
child.sendline("dir")
child.expect_exact("> ")
print(child.before)
child.sendline("cd C:/Users/" + User + "/Desktop")
child.expect_exact("> ")
print(child.before)
It runs cmd.exe, sends command in child.sendline() and looks for prompt child.expect_exact("> ") to get all text generated by command child.before.

How to hardcode bash script in python file

I am writing a python tool that makes some processing, data gathering and eventually calling a bash scripts via subprocess.
The tricky part of my tool is: I use nuitka to compile python files to the single binary file. I'm doing this because I don't want my users to add any features plus I'd like my tool to be mysterious.
The problem is of course, what to do with that bash scripts. For now, I store them together with my nuitka-ed binary. However, due to above, I don't want a bash scripts to be that easily accessible.
For now, I can see two options for me:
I can compile *.sh files and link them with nuitka-ed binary.
I can hardcode *.sh files in *.py files.
Option 1 is rather not an option due to its complexity. Option 2 is slightly better, but for now, my best solutions is following:
I make script.py:
"""
#!/bin/bash
ls -alh /var
echo $?
# (...)
"""
And I inject script.__doc__ to the subprocess.Popen(['bash(...).
Is there any better - more elegant way to achieve my goal while maintaining bash script readability ?
To hardcode bash-code within a python file you could do it this way.
import subprocess
import StringIO
# In Python
text = "foobar"
your_bash_cmd = "echo "+text
process = subprocess.Popen([your_bash_cmd], shell=True, stdout=subprocess.PIPE)
process.wait()
your_bash_output = process.stdout.read()
# Process bash output in python
print(your_bash_output)

python script to edit a file in vim

I want to make a python script that:
opens a file, executes the command i,
then writes 2 lines of code, hits escape
executes the command ZZ.
I was thinking along the lines of os.system("vi program") then os.system("i") and os.system("code"), but that didn't work because you can only execute commands. Thank you!
It's not clear why you want to do this. To truly run an interactive program, you'll have to create a pseudo-tty and manage it from your python script - not for the faint of heart.
If you just want to insert text into an existing file, you can do that directly from python, using the file commands. Or you could invoke a program like sed, the "stream editor", that is intended to do file editing in a scripted fashion. The sed command supports a lot of the ex command set (which is the same base command set that vi uses) so i, c, s, g, a, all work.
THE CODE
import pyautogui
from multiprocessing import Process
import os
vi_proc = Process(target = lambda: os.system("vi program"))
vi_proc.start()
pyautogui.typewrite("i")
pyautogui.typewrite("This code\n")
pyautogui.typewrite("really sucks!")
pyautogui.press("esc")
pyautogui.typewrite("ZZ")
vi_proc.join()
THE BLABLABLA
Well, I really not understand WHY, but I coded a working solution. I used PyAutoGUI, a really simple library that allow you to emulate key and mouse presses and movements.
You may also need to install some sysyem package, like libjpeg8-dev. Furthermore, probably you have also to issue the command xhost + temporarily before installation.
That said, in bash it will be simply:
echo -e "This code\nreally sucks!" > program
If you really want to run VIM from the command-line, you can use the VIM -c option. Something like this:
gvim -c "normal oFirst line" -c "normal oSecond line" -c "ZZ" foo.txt
(Adjust using o, O, i or I as according to where you want the line inserted).
There must be an easier way to insert two lines in a file, though.

Categories