I want to programmatically initialize a Firefox profile so that all files that are normally created on first run of Firefox are created.
I have tried using firefox -CreateProfile but it only creates the folder and a times.json file. I need the full profile. What I probably need to do is start and close Firefox using Python, but I cannot get Firefox to close.
I am using subprocess.Popen so I can retrieve the pid to later close Firefox with proc.terminate(), but it is not working. The pid's process is no longer found. Perhaps it has something to do with Firefox multiprocess?
import os
import subprocess
import time
profile_name = 'new_profile'
profile_path = f"C:\\Users\\user\\profiles\\{profile_name}"
os.system(f'firefox -CreateProfile "{profile_name} {profile_path}" -no-remote')
proc = subprocess.Popen(['firefox', '-profile', profile_path, '-no-remote'])
print(f"Pid: proc.pid")
time.sleep(3)
proc.terminate() # Not working
time.sleep(1)
os.system(f"taskkill /F /pid {proc.pid}") # Process not found
Running the script and confirming with taskkill the process on the original pid is no longer found:
Pid: 16472
ERROR: The process "16472" not found.
How can I close Firefox using this approach?
Related
I’d like to open a few apps using a very simple python script:
from subprocess import call
call("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")
call("/Applications/MongoDB Compass.app/Contents/MacOS/MongoDB Compass")
The problem is that opening them this way seems to open a terminal window along with the app itself - for chrome, it outputs this in the terminal for example:
Last login: Sun Oct 23 00:20:38 on ttys000
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome ; exit;
nick#Nicks-MBP ~ % /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome ; exit;
objc[3817]: Class WebSwapCGLLayer is implemented in both /System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/Frameworks/libANGLE-shared.dylib (0x7ffb45565ec8) and /Applications/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Versions/106.0.5249.119/Libraries/libGLESv2.dylib (0x116ba9668). One of the two will be used. Which one is undefined.
So it hijacks the terminal and does not proceed to this next line:
call("/Applications/MongoDB Compass.app/Contents/MacOS/MongoDB Compass")
If I try to call these:
call(("/Applications/Google Chrome.app"))
call(("/Applications/MongoDB Compass.app"))
I get this error, with other posts stating that it may be a dir and not an app:
OSError: [Errno 13] Permission denied
How can this be fixed? Note that I do not want to do this despite it working:
os.system("open /Applications/" + app + ".app")
Because I need to be able to wait for the apps to finish opening before running another command, hence the use of Subprocess.call. Thank you.
UPDATE:
I now have this:
print("start")
call(
[("/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome")],
shell=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT,
)
print("end")
But the print("end") line only executes when I exit out of chrome. How can I get it to wait for Chrome to load and then print 'end' after? Also it requires Shell=True for some reason, otherwise it complains with:
FileNotFoundError: [Errno 2] No such file or directory: '/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome
Updated Answer
This also appears to work and doesn't involve the shell:
import subprocess as sp
print("start")
sp.run(["open", "-a", "Google Chrome"])
print("end")
Original Answer
This appears to do what you want, though I have no explanation as to why:
import subprocess as sp
print("start")
sp.Popen(
["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"],
stdin =sp.DEVNULL,
stdout=sp.DEVNULL,
stderr=sp.DEVNULL)
print("end")
I have a batch script which eventually runs two python file (one after another), but I am unable to handle the exit code from one workflow to another. Due to which my batch script is failing
batch file snippet:
#echo off
echo "Starting the automation Script"
cd "C:\Desktop\AutoImpement\"
echo "running the loging"
start python login.py
start python OrderTicket.py
pause
login script:
import time
from selenium import webdriver
browser = webdriver.Chrome(executable_path="C:\Desktop\AutoImpement\ChromeDriver")
browser.get('https://localhost:8080/login/#')
browser.find_element_by_id(“Login”).send_keys(“<userName>”)
browser.find_element_by_id (“Password”).send_keys(“password”)
browser.find_element_by_id(“submit”).click()
time.sleep(5)
browser.find_element_by_id(“ItemName”).send_keys(“test”)
browser.find_element_by_id (“Quantity”).send_keys(“5”)
browser.find_element_by_id(“Address”).send_keys(“Test”)
browser.find_element_by_id(“submitOrder”).click()
time.sleep(3)
browser.quit()
Verify the Order Script
import time
from selenium import webdriver
browser = webdriver.Chrome(executable_path="C:\Desktop\AutoImpement\ChromeDriver")
browser.get('https://localhost:8080/OrderDetails')
browser.find_element_by_id(“SreachOrder”).send_keys(“test”)
browser.find_element_by_id(“findOrder”).click()
time.sleep(3)
browser.quit()
When I run the batch file, only the login script is running successfully but the control is not shifting to the next script which verifies the order from the first file. I tried with sending the exit code from the python by changing the following but didn't work.
import time
from selenium import webdriver
try:
browser = webdriver.Chrome(executable_path="C:\Desktop\AutoImpement\ChromeDriver")
browser.get('https://localhost:8080/login/#')
browser.find_element_by_id(“Login”).send_keys(“<userName>”)
browser.find_element_by_id (“Password”).send_keys(“password”)
browser.find_element_by_id(“submit”).click()
time.sleep(5)
browser.find_element_by_id(“ItemName”).send_keys(“test”)
browser.find_element_by_id (“Quantity”).send_keys(“5”)
browser.find_element_by_id(“Address”).send_keys(“Test”)
browser.find_element_by_id(“submitOrder”).click()
time.sleep(3)
exit(0)
except:
print("Error Occured")
exit(1)
finally:
browser.quit()
In the above case in your batch file. Both the Scripts will run simultaneously.
Remove Start
python login.py
python OrderTicket.py
The Second will run only after first is complete.
There is a test, smth like:
import //needed imports
public class TestClass{
WebDriver driver;
#Before
public void setUp() {
//some code
}
#Test
public void test1() {
//some code, including init of driver (geckodriver)
}
//#After
// public void tearDown() {
// driver.quit();
//}
}
So, I inited geckodriver, and successfully running my tests, using firefox instances.
But I want Not to close firefox window after each run, because I just want to analyse what I have, and fix any needed, after test run(I'm going to unComment driver.quit() later).
At the same time, each calling without closing the driver leads to over-impact to RAM on my PC(and does not matter - did I close browser manually, or not, after test):
So, question is:
is there any way to close the process(more precisely - do smth, which will close geckodriver.exe process in taskmgr) of "geckodriver", but will NOT close the browser after test finished? e.g., adding some method in test itself, whatever... This not impacts my work/test itself, I just want to add some optimizing.
As per your question commenting out driver.quit() just Not to close firefox window after each run, because I just want to analyse what I have won't be a part of best practices.
For any detailed analysis we can create log entries and take snapshots.
While automating through Selenium as per the best practices you should invoke the quit() method within the tearDown() {}. Invoking quit() DELETEs the current browsing session through sending "quit" command with {"flags":["eForceQuit"]} and finally sends the GET request on /shutdown EndPoint. Here is an example below :
1503397488598 webdriver::server DEBUG -> DELETE /session/8e457516-3335-4d3b-9140-53fb52aa8b74
1503397488607 geckodriver::marionette TRACE -> 37:[0,4,"quit",{"flags":["eForceQuit"]}]
1503397488821 webdriver::server DEBUG -> GET /shutdown
So on invoking quit() method the Web Browser session and the WebDriver instance gets killed completely. Hence you don't have to incorporate any additional steps which will be an overhead.
Solution
Still if you want to execute kill the dangling WebDriver instances e.g. GeckoDriver.exe instances you can use either of the following code block to kill any of the dangling WebDriver instances :
Java Solution(Windows):
import java.io.IOException;
public class Kill_ChromeDriver_GeckoDriver_IEDriverserver
{
public static void main(String[] args) throws Exception
{
Runtime.getRuntime().exec("taskkill /F /IM geckodriver.exe /T");
Runtime.getRuntime().exec("taskkill /F /IM chromedriver.exe /T");
Runtime.getRuntime().exec("taskkill /F /IM IEDriverServer.exe /T");
}
}
Python Solution (Windows):
import os
os.system("taskkill /f /im geckodriver.exe /T")
os.system("taskkill /f /im chromedriver.exe /T")
os.system("taskkill /f /im IEDriverServer.exe /T")
Python Solution(Cross Platform):
import os
import psutil
PROCNAME = "geckodriver" # or chromedriver or IEDriverServer
for proc in psutil.process_iter():
# check whether the process name matches
if proc.name() == PROCNAME:
proc.kill()
I'm working on a program that requires me to keep track of the PIDs of specific Chrome/browser instances. This is the code I wrote for this:
def launch_procs():
low1 = Popen(['google-chrome-stable', 'http://www.google.com'])
med1 = Popen(['google-chrome-stable', 'http://www.netflix.com'])
high1 = Popen(['google-chrome-stable', 'http://www.facebook.com'])
return [low1.pid, med1.pid, high1.pid]
However, when I attempt to reference the PIDs later on in the program it seems that the PIDs have expired. Here is the error I get:
7894
strace: attach: ptrace(PTRACE_ATTACH, ...): No such process
7896
strace: attach: ptrace(PTRACE_ATTACH, ...): No such process
7901
strace: attach: ptrace(PTRACE_ATTACH, ...): No such process
Is the issue that Chrome doesn't assign permanent PIDs to its tabs/processes (i.e. it forks once a Chrome process launches and ditches the parent process)?
Note: This implementation is browser/implementation agnostic, I just need a way to obtain stable access to the PIDs of these launched processes. If anyone has suggestions on doing this they would be very much appreciated.
Thanks!
Chrome does not run as root under normal operating conditions. You can find several discussions for this here and here
There are several arguments that will allow you to circumvent this. By passing --user-data-dir and --no-sandbox you will be able to run chrome as root.
import os
from subprocess import Popen
line_count = 10
outfile = 'foo.txt'
cmd = 'sudo timeout 10 strace -p {} -o temp.out | cat temp.out | tail -{} > {}'
tab_sites = ['www.google.com', 'www.yahoo.com', 'www.msn.com']
for site in tab_sites:
chrome_proc = Popen(['google-chrome-stable', site, '--user-data-dir', '--no-sandbox'])
print(chrome_proc.pid)
os.system(cmd.format(chrome_proc.pid, line_count, outfile))
Alternatively you can use runuser with your command:
import os
import sys
from subprocess import Popen
line_count = 10
outfile = 'foo.txt'
cmd = 'sudo timeout 10 strace -p {} -o temp.out | cat temp.out | tail -{} > {}'
tab_sites = ['www.google.com', 'www.yahoo.com', 'www.msn.com']
for site in tab_sites:
chrome_proc = Popen(['runuser', '-u', sys.argv[1], 'google-chrome-stable', site])
print(chrome_proc.pid)
os.system(cmd.format(chrome_proc.pid, line_count, outfile))
Just pass in the username you want to run this under, sudo python trace_chrome.py your_user_name
I understand you aren't able to show your exact code which does make things tougher to be able to assist.
To see the Process ID's of your Chrome tabs you can open the Task Manager by pressing Shift Esc. I did some testing, and as you suspect, the PID is different than reported by Popen.
One way to get an accessable PID with Chrome is to use the option --temp-profile to create a new session for each site instead of using an existing one.
I am playing around with web scraping and Tor.
I managed to make it work with both requests and Selenium + PhantomJS. However, I need that the Tor browser is opened for the script to work.
This is why I am trying now to automatise the complete process; that is: open Tor browser automatically, run some script and at the end close the browser automatically. But I am struggling with it.
#open Tor browser
os.system('open /Applications/TorBrowser.app')
#code to scrape
#close Tor browser
???
Open
To open the browser, some other options I found out there are not working.
import subprocess
subprocess.Popen('/Applications/TorBrowser.app') #permission denied
or
os.system('start /Applications/TorBrowser.app') #sh: start: command not found
However, the following line worked:
os.system('open /Applications/TorBrowser.app')
Close
The main problem is to close the browser afterwards, as none of the commands found in other posts worked.
Those include:
os.system("taskkill /im /Applications/TorBrowser.app /f") #sh: taskkill: command not found
or
os.system("kill /Applications/TorBrowser.app") #sh: line 0: kill: /Applications/TorBrowser.app: arguments must be process or job IDs
or
os.close('/Applications/TorBrowser.app') #TypeError: an integer is required (got type str)
Any suggestions of how to close it?
And is there a better way to open it?
Edit: I'm on Mac with Python 3.
This worked for me:
from selenium import webdriver
import os
import subprocess
#start Tor
sproc=subprocess.Popen('"C:\\Users\\My name\\Desktop\\Tor Browser\\Browser\\firefox.exe"' )
#start PhantomJS
service_args = [ '--proxy=localhost:9150', '--proxy-type=socks5', ]
driver = webdriver.PhantomJS(service_args=service_args)
#get page
driver.get("https://stackoverflow.com/questions/40161921/how-to-open-and-close-tor-browser-automatically-with-python")
print(driver.page_source)
driver.close()
#kill process
sproc.kill()
I think you should add some time pauses between commands:
import time
time.sleep(20)# wait 20 seconds
Another way to open Tor:
os.system('"C:\\Users\\My Name\\Desktop\\Tor Browser\\Browser\\firefox.exe"' )
But this time your command will wait until the called process stops himself (may be user will close it). According to your question it is not what you want. To control executing process let it runs and use special variable to kill it whenever you want.
Also pay attention to string path: double quotes inside single quotes. There are other ways to pass strings with spaces to system commands, for example: running an outside program (executable) in python?.
Try this in jupyter:
import webbrowser
urL='https://YOUR WEBSITE ADDRESS HERE'
mozilla_path="C:\\Users\\T14s\\Desktop\\Tor Browser\\Browser\\firefox.exe"
webbrowser.register('firefox', None,webbrowser.BackgroundBrowser(mozilla_path))
webbrowser.get('firefox').open_new_tab(urL)
import os
import time
time.sleep(10)
os.system("taskkill /im firefox.exe /f")
TOR is based on firefox - hence firefox comes up a lot.