Can I control a Powershell session from Python? - python

I want to initialise a powershell subprocess and be able to send commands to it and receive its output using Python on Windows.
Please can someone help with simple examples? I have gone through almost every other post similar to this on here but haven't had any luck with my specific problem...
I am to run this code to automate a current manual process conducted on Powershell.
This is a high level look at what I want to achieve using Python
I want to launch a powershell session using Python
Then CD into a directory
Run a powershell script in that directory
Display/retrieve all outputs
And pass new commands in the same session, again, whilst capturing outputs
So far all I have is the following code which launches powershell and runs a .ps1 file by giving directory. I'm not sure how to proceed from here or if this is even the best approach given the steps I need to undertake shown above.
p = subprocess.Popen(["powershell.exe", Powershell.exe -executionpolicy remotesigned -File 'G:\My Documents\helloworld.ps1';"]. stdout=sys.stdout)
p.communicate()
After running the above code, python terminal displays the message 'Test Message' correctly

Related

why the same powershell command run on the powershell console but not using os.system?

I would like to include a command to create a 7zip archive withinin a Python script. Since I am working on Windows, I need to pass the command to the powershell console. I am planning to do it with os.system (I am aware that this is not the best way to do it and that I should use subprocess, but I really just need a quick fix and it would not be time effective for me to learn to use a new module in this context).
The following command works if run from the powershell console
&'C:\\Program Files\\7-Zip\\7z' a -mx=0 X:/myarch.zip X:/myarch
So I recreate the same string within python like this:
cmdl = r"&'C:\\Program Files\\7-Zip\\7z' a -mx=0 X:/myarch.zip X:/myarch"
The string is interpreted as follow:
"&'C:\\\\Program Files\\\\7-Zip\\\\7z' a -mx=0 X:/myarch.zip X:/myarch"
Now, if I copy-paste the above string within the powershell console, it runs without problems. However, if I run it within python using os.system(cmdl) I got the following error
"The filename, directory name, or volume label syntax is incorrect"
Why is this the case and how can I fix this issue ?
os.system is meant for executing cmd commands, cmd commands can be ran in powershell maybe after all powershell is a bit advanced but I'm sure that you can't run a cmd command in powershell, henceforth your code is not working.
However a creative solution for executing a powershell command from python(not using python) would be to write your command into a .ps file(powershell script)and then run it using os.startfile()(use this code: os.startfile("script.ps"))

How to send value from python script to console and exit

My python script generate a proper command that user need to run in the same console. My scenario is that user is running a script and then as a result see the command that must to run. Is there any way to exit python script and send that command to console, so user do not need to copy/paste?
A solution would be to have your python script (let's call it script.py) just print the command: print('ls -l') and use it in a terminal like so: $(python3 script.py). This makes bash run the output of your script as a command, and would basically run a ls -l in the terminal.
You can even go a step beyond and create an alias in ~/.bashrc so that you no longer need to call the whole line. You can write at the end of the file something like alias printls=$(python3 /path/to/script.py). After starting a new terminal, you can type printls and the script will run.
A drawback of this method is that you have no proper way of handling exceptions or errors in your code, since everything it prints will be run as a command. One way (though ugly) would be to print('echo "An error occured!"') so that the user who runs the command can see that something malfunctioned.
However, I'd suggest going for the "traditional" way and running the command directly from python. Here's a link to how you can achieve this: Calling an external command in Python.
Python can run system commands in new subshells. The proper way of doing this is via the subprocess module, but for simple tasks it's easier to just use os.system. Example Python script (assuming a Unix-like system):
import os
os.system('ls')

No stdout/stdin when calling python script from powershell

I've got a strange situation, that makes me feel I went wrong at some point.
Environment: I'm running powershell .ps1 script (tried both: powershell and ISE) on Windows 10. In this script I'm runing python (2.7.14) script.
The issue is that I cannot see any output from this python script. This troubles me, because I cannot see the password prompt (https://docs.python.org/2/library/getpass.html used inside) and cannot enter the password.
Tried at least following script invocation methods ($python="C:\Python27_x86\python.exe"):
. $python ...
& "$python ..."
Start-Process $python ...
cmd /c "$python ..." (as suggested in PowerShell is Buffering Python Stdout)
Any ideas, what is the reason for such behavior and how can I pass the password to the script?
There must be a better way to do this than e.g.: Powershell: Capture program stdout and stderr to separate variables

Issue terminal commands that are piped to a shell script

I have what seems to be a simple use case: I launch a script (python or bash) which runs an emulator from command prompt and then the emulator takes commands until I type ctrl-c or exit. I want to do this same thing from a shell and my code below isn't working. What I am trying to do is test automation so I want to issue commands directly to the application from command shell. In python, I have the following:
import os
import subprocess
command = ['/usr/local/bin/YCTV-SIM.sh', '-Latest'] #emulator for yahoo widgets
process = subprocess.Popen( command, shell=True, stdin=subprocess.PIPE )
time.sleep(12) #wait for launch to finish
print '/widgets 1' #first command to issue
print '/key enter' #second command to issue
process.wait()
As you can see, this is some pretty simple stuff. When 'YCTV-SIM.sh' is launched from the command shell, I am put into an input mode and my key entries are sent to the application shell (YCTV-SIM.sh reads raw input) so ideally, I would be able to pipe text directly to this application shell. So far tho, nothing happens; test outputs to the console window but the application does not respond to the commands that I attempt to issue. I am using python 2.6.3, if that matters, but Python is not required..
Language is immaterial at this point so PERL, Python, Bash, TCL... whatever you can suggest that might help.
You need to redirect stdin of the child process and write into it. See e.g. subprocess.Popen.communicate.

python multithreading issue in cronjob

I have a python program that uses the ThreadPool for multithreading. The program is one step in a shell script. When I execute the shell script manually on the command line, the entire flow works as expected. However, when I execute the shell script as a cronjob, it appears that the flow goes to the next steps before the python multithreading steps are completely finished.
Inside the python program, I do call AsyncResult.get(timeout) to wait for all the results to come back before moving on.
Run your program via batch(1) (see the output of the command man batch) as well. If that works OK, but the cron version does not, then it is almost certainly a problem with your environment variable setup. To verify that, run printenv from your interactive shell to inspect your environment there. Then do the same thing inside the crontab (you will just need to temporarily set up an extra cron entry for it). Try setting the variables in your shell script before invoking Python.
On the other hand, if it doesn't work via batch(1) either, it could be something to do with the files that your code has open. Try running your shell script with input redirected from /dev/null and output going to a file:
$ /usr/local/bin/myscript </dev/null >|/tmp/outfile.txt 2>&1
Try setting "TERM=xterm" (or whatever env variable you have, figure out by command 'env' on your terminal) in your crontab.

Categories