I am trying to create a GUI to create and activate Python virtual environments using subprocess and platform modules. The code I have written was not tested on Windows and Mac but does not work on Ubuntu. The venv is not created nor started when I run the code. Here is the code:
import subprocess
import platform
env = 'testenv'
def create_venv(venv_name):
if platform.system() == 'Windows':
command = f'python -m venv {venv_name} & {venv_name}\\Scripts\\activate.bat'
subprocess.Popen(['cmd', '/c', command])
elif platform.system() == 'Darwin':
command = f'python3 -m venv {venv_name}; source {venv_name}/bin/activate'
subprocess.Popen(['osascript', '-e', f'tell app "Terminal" to do script "{command}"'])
elif platform.system() == 'Linux':
command = f'python3 -m venv {venv_name}; exec bash'
subprocess.Popen(['gnome-terminal', '--', 'bash', '-c', command])
def stop_venv(venv_name):
if platform.system() == 'Windows':
command = f'activate {venv_name} && deactivate'
subprocess.Popen(['cmd', '/c', command])
elif platform.system() == 'Darwin':
command = f'source {venv_name}/bin/activate && deactivate'
subprocess.Popen(['osascript', '-e', f'tell application "Terminal" to do script "{command}"'])
elif platform.system() == 'Linux':
command = f'source {venv_name}/bin/activate && deactivate'
subprocess.Popen(['x-terminal-emulator', '-e', f'/bin/bash -c "{command}; exec /bin/bash"'])
def start_venv(venv_name):
if platform.system() == 'Windows':
command = f'{venv_name}\\Scripts\\activate.bat'
subprocess.Popen(['cmd', '/c', command])
elif platform.system() == 'Darwin':
command = f'source {venv_name}/bin/activate'
subprocess.Popen(['osascript', '-e', f'tell app "Terminal" to do script "{command}"'])
elif platform.system() == 'Linux':
command = f'source {venv_name}/bin/activate; exec bash'
subprocess.Popen(['gnome-terminal', '--', 'bash', '-c', command])
create_venv(env)
start_venv(env)
I have tried to use xterm instead of gnome-terminal but it did not work either.
Can someone please help me figure out what the issue might be and how I can modify the code to make it work on Ubuntu? Thank you in advance.
Please note that running the 'create_venv' function will continuously open new terminal windows until the user stops the script with CTRL + C.
Related
shell script:
#!/bin/bash
scp -q /local/opt/file_test remote_host:~/ 2>&1
echo $?
exit 0
python code:
import subprocess
from multiprocessing import Process
import os
import signal
import sys
from multiprocessing import set_start_method
def _detach_with_context(executor):
# 放在context外面, 减少开销
os.setsid()
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
pid = os.fork()
if pid > 0:
sys.exit(0)
try:
if pid < 0:
sys.exit(0)
# 执行任务
executor()
except Exception as ex:
pass
finally:
sys.exit(0)
def detach_autosql_execute(executor):
try:
p = Process(target=_detach_with_context, args=(executor,))
p.start()
p.join()
except Exception as ex:
executor.failure(f'create daemon process error: {ex}')
def execute():
command='sh ./test.sh'
p = subprocess.Popen(
command.encode('utf-8'),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
encoding='UTF-8'
)
print(''.join(p.stdout.readlines()))
if __name__ == '__main__':
set_start_method('spawn')
detach_autosql_execute(execute)
The local host and the remote host 'remote_host' are ssh password-less login.
The 'echo $?' normal is 0, but the shell script echo $? is 1,
When I exec the shell script only by command, the echo $? is 0
When I exec the shell script in one fork process, the echo $? is 0
But when i exec the shell script in two fork process, the echo $? is 1
Why?
You use in your script ~/ to denote your home directory, but this is a bash feature. However you run your script using sh ./test.sh, which means it is executed by POSIX shell. I suggest that you invoke your script by bash ./test.sh or specify your home directory in the script by $HOME instead of ~.
UPDATE: Why it still is not a good idea to run a script which is (based on its #! line) intended for bash, using sh, your usage of tilde expansion should not cause any difference, as #tripleee pointed out in their comments.
I tried the below approach to open a command prompt and run a sample command. But it immediately closes:
import os
# as of now i am just passing cd /../, later will be changing to a different command
os.system("start /wait cmd /c {cd /../}")
I also tried this way, but this opens two command shells:
import os
os.system("start /B start cmd.exe #cmd /k cd /d D:")
Is it possible to just open one command prompt and run the command?
import subprocess
cmd = subprocess.Popen('cmd.exe /K cd /')
#subprocess.Popen('cmd.exe /K netstat') # run cmd commands like netstat,..etc
#subprocess.Popen('cmd.exe /K python') # open cmd in Python live interpreter mode
#subprocess.Popen('cmd.exe /K my_script.py') # run your python script
read more https://docs.python.org/3/library/subprocess.html#subprocess.Popen
The CMD window will run the commands you give it and then immediately close on completion, if you want to keep the window open you need to send a pause command:
os.system("YOUR COMMAND")
os.system("pause")
OS:Ubuntu 16.04LTS.
Python automation.
Hi, i am trying to do python automation in ubuntu, where i have to invoke a shell script programmatically, after invoking shell script i need to enter and execute terminal commands.
i am invoking shell script with below commands
import os
os.system("gnome-terminal --working-directory='/home/murlee/CTS/android-cts/tools' -e 'bash -c \"./cts-tradefed; exec bash\"'")
*now i need help to enter and executing terminal commands after invoking the shell script
after invoking shell script my terminal will look like this
Terminal_snapshot
"murlee#murlee-Lenovo-ideapad-100-14IBD:~/CTS/android-cts/tools$
./cts-tradefed
Android CTS 6.0_r17 build: 3866870
cts-tf >(here i have to enter commands and execute)"
Thanks!
Create an init script named my-init.sh
./cts-tradefed
Now call
import os
wd = '/home/murlee/CTS/android-cts/tools'
cmd = "bash --init-file {0}".format('./my-init.sh')
os.system("gnome-terminal --working-directory='{0}' -e '{1}'").format(wd,cmd)
I am trying to automate the process of installing the docker-engine and then asking the user if he would like to pull rhel/suse/centos images.
Using python was my first idea but I have added bash script to make things easier, python seemed not too friendly to run cli commands.
Now, I am planning to expand the functionality and shell script will not scale.
How do I convert this script to python? Many common command line operations such as "yum install",etc are not easy without using additional python imports.
If you have any easier suggestions, please advice
Thanks!
This is bash script still in the works...
#!/bin/sh
if [ "$(id -u)" != "0" ]; then
echo "This script must be run as root" 1>&2
exit 1
fi
echo
echo " - Installing packages"
echo
if [[ -e /usr/bin/yum ]]; then
#Verify packages are up to date
yum update
#Install Docker
yum install docker-engine
else
echo "No yum, lets try apt-get"
sudo apt-get update
#sudo apt-get -y upgrade
#sudo apt-get install linux-image-extra-`uname -r`
#sudo apt-get install docker-engine
fi
if [ $? -eq 0 ]; then
echo success
else
echo failed
exit
fi
#start Docker
echo "Would you like to start Docker and pull Images? Select 1 or 2"
select y1 in "Yes" "No"; do
case $y1 in
Yes ) service docker start; docker pull "rhel:7.2" ;docker pull "mstormo/suse" ;break;;
No ) exit;;
esac
echo " - Complete!"
echo
done
Ok, so I was able to make it work in Python. I will leave the code here, in case anyone needs it.
Cheers!
Rohit
from subprocess import Popen, PIPE
uid = Popen(['id', '-u'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
uid_get = uid.stdout.read(1)
if uid_get != '0':
print "This script needs to be run as root"
print " - Installing packages "
check1 = Popen(['/usr/bin/yum'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
check_yum = check1.stdout.read()
if check_yum == ' ':
print "Yum is not found, trying apt-get"
proc = Popen('apt-get update', shell=True, stdin=None, executable="/bin/bash")
proc.wait()
proc = Popen('apt-get upgrade', shell=True, stdin=None, executable="/bin/bash")
proc.wait()
proc = Popen('apt-get install', shell=True, stdin=None, executable="/bin/bash")
proc.wait()
proc = Popen('apt-get install docker-engine', shell=True, stdin=None, executable="/bin/bash")
proc.wait()
else:
print "Running yum install"
proc = Popen('yum update', shell=True, stdin=None, executable="/bin/bash")
proc.wait()
proc = Popen('yum install docker-engine', shell=True, stdin=None, executable="/bin/bash")
proc.wait()
print "Would you like to start Docker and pull images - RHEL and SUSE? -> y or n ?"
y="yes"
n="no"
choice = raw_input().lower()
if choice in y:
print "Pulling RHEL and SUSE images"
proc = Popen('service docker start; docker pull "rhel:7.2" ;docker pull "mstormo/suse" ; docker run rhel sh -c "cat /etc/*release"; docker run "mstormo/suse" sh -c "cat /etc/*release"', shell=True, stdin=None, executable="/bin/bash")
proc.wait()
elif choice in n:
print "Thank you, exiting...."
else:
print " Invalid selection"
print " - Complete! "
I would suggest trying the sh module:
from sh import docker
for line in docker('build', '-t', some_tag, '.', _iter=True):
sys.stdout.write(str(line))
This is a long running command so it is nice to show its output
line by line. This is what the for loop and _iter does.
When a terminal is opened, the environmental shell is set. If I then type "csh" it starts running a c shell as a program within the bash terminal. My question is, from a python script, how can I check to determine if csh has been executed prior to starting the python script.
THanks
You can check the shell environment by using
import os
shell = os.environ['SHELL']
Then you can make sure shell is set to /bin/csh
You can use os.getppid() to find the parent PID, and ps to find the name of the command:
import subprocess
import os
ppid = os.getppid()
out = subprocess.check_output(['ps', '--format', '%c', '--pid', str(ppid)])
print(out.splitlines()[-1])
% csh
% script.py
csh
% bash
(dev)13:53:04 unutbu#buster:~% script.py
bash
Note that the parent process may not be a shell. If I run the code from an IPython session launched inside emacs, then the parent is emacs:
In [170]: ppid = os.getppid()
out = subprocess.check_output(['ps', '--format', '%c', '--pid', str(ppid)])
print(out.splitlines()[-1])
In [172]: emacs