Why do I get "webbrowser.Error: could not locate runnable browser"? - python

I'm new to coding in python and I'm wondering if some one can explain why this code works on the second try but not on the first?
I was just trying to open a browser that was not the default one.
first try --> did not work
import webbrowser
url='https://www.mozilla.org'
webbrowser.register('firefox', None)
webbrowser.BackgroundBrowser("C:\\Program Files\\Mozilla Firefox\\firefox.exe")
webbrowser.get('firefox').open(url)
webbrowser.Error: could not locate runnable browser
Process finished with exit code 1
second try --> works
import webbrowser
url='https://www.mozilla.org'
webbrowser.register('firefox', None, webbrowser.BackgroundBrowser("C:\\Program Files\\Mozilla Firefox\\firefox.exe"))
webbrowser.get('firefox').open(url)
Process finished with exit code 0

Like you can see here, register tells Python where the webbrowser with the name "firefox" can be found. You have to pass an instance (BackgroundBrowser) or a constructor. In the first code snippet you pass None as the constructor, which is not a valid browser class, it can thus not find/create the browser and cannot register it. In the second snippet you pass your BackgroundBrowser instance and thus it can register this valid browser as "firefox" and you can run it later.
The 5th line (webbrowser.BackgroundBrowser...) in the first snippet does basically nothing, you are supposed to give that as an argument to register like you do in the second snippet.

Related

Why does Python seem to run the else statement although the if clause is true?

I tried to write a simple program in Python 3.10 that opens (at least) one browser window and can take input from the command line to open additional windows:
import webbrowser
import sys
if len(sys.argv) > 1:
for a in range(len(sys.argv)):
webbrowser.open(sys.argv[a])
else:
webbrowser.open("www.google.com")
I run that from a one-line batchfile so I can enter additional websites to open. That does work well, however, it always opens Google, no matter if command line arguments are passed or not (if I just run it without arguments, it opens Google. If I run it with e.g. LinkedIn as an argument, it opens Google and LinkedIn. If I use wikipedia and LinkedIn as arguments, it opens both of these plus Google etc).
However what I want is that Google is only opened when no arguments are passed... The strange thing is that when I run the exact same code, but replace the webbrowser.open() with a print statement, it does exactly what it is supposed to do:
import sys
if len(sys.argv) > 1:
for a in range(len(sys.argv)):
print(sys.argv[a])
else:
print("www.google.com")
Passing command line arguments to this code causes it to only print the arguments, "www.google.com" is only printed when no arguments are passed.
I am sorry, but I am completely lost why these two codes act differently. I address both by running a batch file that goes
#py.exe C:\Users\[Route to the file]\[File].py %*
What I have tried is replacing the else statement by elif len(sys.argv) == 1, but that acts exactly the same. The only differnce I see is the usage of the webbrowser module. Can importing a module change behaviour of the code in that way?
Thank you in advance!
argv captures the python script name and the website, which you already know because you're checing if len > 1. However you're then iterating over all args, causing the browser to attempt to load both the script name and the website as websites. Since the script name is not a valid url, I'm assuming your browser is opening to your default page, which happens to be google.com.
You need to skip the first arg, which you can do by sys.arvg[1:]
import webbrowser
import sys
if len(sys.argv) > 1:
for a in sys.argv[1:]:
webbrowser.open(a)
else:
webbrowser.open("www.google.com")

Can't open Microsoft Teams with python (3.8) script using any method

I am trying to make a script to automate the login into Microsoft Teams and all of my code works except the part where the application has to be opened. The weird thing is that this is capable of opening any other application except MS Teams (Chrome, Notepad, Firefox, Edge etc.)
Here's the relevant code:
def openfile():
if os.stat("stor.txt").st_size == 0:
name = filedialog.askopenfilename()
newfile = open("stor.txt", "w")
newfile.write(name)
else:
name = (open("stor.txt", "r").read())
os.startfile(name)
sleep(5)
keyboard.write(open("user.txt", "r").read())
keyboard.press("enter")
sleep(3)
keyboard.write(open("pass.txt", "r").read())
keyboard.press("enter")
I tried this with os.startfile, os.system(start..) and every other method on the web. Doesn't work.
The value I'm passing in to os.startfile() when I try to run Teams is C:/Users/Raghav/AppData/Local/Microsoft/Teams/Update.exe.
First of all, I don't recommend storing your password in plain text like that. It's not very secure, and if another program takes focus at the right time your code will even type your password somewhere else!
Teams should remember your credentials after the first time you log in. I suggest letting it handle that part.
In any case, running os.startfile("foo.exe") is like double-clicking on foo.exe. The file name that you're passing in is C:/Users/Raghav/AppData/Local/Microsoft/Teams/Update.exe, and Update.exe doesn't look like something that should launch Teams to me.
Inspecting the Teams shortcut in my own Start menu, I see that things are a bit more complicated. This shortcut runs Update.exe and passes it some arguments:
C:\...\Update.exe --processStart "Teams.exe"
There is no way to pass arguments to a program with os.startfile(). Try os.system() instead:
os.system('C:/Users/Raghav/AppData/Local/Microsoft/Teams/Update.exe --processStart "Teams.exe"')
There are lots of other ways to run external commands in Python, but this is likely simplest since you don't need Teams' output streams. This command should return 0 if it succeeds and some other value if it fails.
import os
os.system("C:\\Users\\Lenovo\\AppData\\Local\\Discord\\Update.exe --processStart Discord.exe")
For applications that have an address like above, there are also some tips:
Sometimes Discord.exe name of the file in the address have "Discord.exe" (with double-quotes). Remove it.
Instead of single \ use double \\ in the address.
It will definitely work GO AHEAD ✔

Python Selenium geckodriver print silently breaks printing

I have searched and tried different things for days and I came up empty handed. The code is fairly straight forward.
from selenium import webdriver
import os
downloadfolder = os.path.join(os.path.expanduser("~/"),"mydownload")
os.chdir(downloadfolder)
profile = webdriver.FirefoxProfile(downloadfolder)
profile.set_preference('print.always_print_silent',True)
profile.set_preference('print_printer','Print to File')
profile.set_preference('print.print_to_filename',
os.path.join(downloadfolder,'print.pdf'))
driver.webdriver.Firefox(profile)
driver.get("https://www.google.com") # or whatever site
driver.execute_script("window.print();")
This setup used to work, up to about a week ago, when I have noticed I am not getting the screen print.
When I try to print manually, I will get "An error occurred while printing".
What I have noticed in "about:config" on Firefox is that when I hit print, it will defaults to "PostScript/default". And no matter what I set it to, it will default to this value the moment I click on print.
Another thing that got me scratching my head. This does not happen if I don't set
profile.set_preference('print.always_print_silent',True)
But the dialog box shows. Any help appreciated.

Python Selenium Code behaving differently depending on calling mode

I've tripped on a very easy to reproduce code that's driving me crazy.
I'm trying to take a picture of the screen after entering a container code in a website form, using Python and PhantomJS webdriver (selenium).
The code that makes it possible is quite short, and reproducing it in the console works fine. But if this same code is within a function or a script, it doesn't behave the same.
Here is the working code, that works for me writing it line by line in the console:
(Python version 2.7.9, selenium 2.53.6)
> python
from selenium import webdriver
driver = webdriver.PhantomJS()
driver.set_window_size(1280, 1024)
driver.get('http://www.track-trace.com/container')
driver.find_element_by_name('number').clear()
driver.find_element_by_name('number').send_keys('CGMU5109933')
driver.find_element_by_xpath('//input[#name="commit" and #value="Track direct"]').click()
driver.save_screenshot('./x.png')
However, this same code inside a function or a script only behaves the same until it reaches the click.
It freezes while loading, and the screenshot shows just that.
It doesn't matter what type of wait I try, implicit or explicit, the loading button won't end.
Here is the same code inside a function in foo.py module to make trying it easier.
The picture that is taken won't match the picture taken by the above code.
# foo.py
from selenium import webdriver
def try_it():
driver = webdriver.PhantomJS()
driver.set_window_size(1280, 1024)
driver.get('http://www.track-trace.com/container')
driver.find_element_by_name('number').clear()
driver.find_element_by_name('number').send_keys('CGMU5109933')
driver.find_element_by_xpath('//input[#name="commit" and #value="Track direct"]').click()
driver.save_screenshot('./x.png')
> python
>>> import foo
>>> foo.try_it()
The code must be in a function as it is called on demand when new search petitions arrive on a web service that is integrated in an application.
I always seek first for questions that may have valid answers but this time it doesn't seem to be anything similar to my problem.
Any idea why this may be happening and how to avoid it would be very much appreciated. If any other code or clarification is needed don't hesitate to ask.
This is purely a timing issue. Button clicks don't block, meaning once a click is issued, it returns and python runs the very next line right away. You need to wait until the next page has finished loading before you can take the screenshot. I would use an explicit wait that blocks until an element on the next page you're interested in has loaded. Likewise, I think you do need to worry about the popup asking if you really want to use direct.
My script:
from explicit import waiter
from selenium import webdriver
from selenium.webdriver.common.by import By
def locate_container(driver, container_id):
url = 'http://www.track-trace.com/container'
track_direct_xpath = '//input[#name="commit" and #value="Track direct"]'
im_sure_css = 'div.modal-footer button.jq-directinfo-continue'
tracking_details_header_css = 'div#wrapper > div.inner > h1'
# Load the container search page
driver.get(url)
# Locate the container field, enter container_id, click direct search button
waiter.find_write(driver, 'number', container_id, clear_first=True, by=By.NAME)
waiter.find_element(driver, track_direct_xpath, By.XPATH).click()
# Locate I'm Sure button and click it
waiter.find_element(driver, im_sure_css, By.CSS_SELECTOR).click()
# Wait for the "Tracking details for Container: XXX" header to load
waiter.find_element(driver, tracking_details_header_css, By.CSS_SELECTOR)
# Now we know the page has loaded and we can take the screenshot:
driver.save_screenshot('./x.png')
def main():
driver = webdriver.PhantomJS()
try:
driver.set_window_size(1280, 1024)
locate_container(driver, 'CGMU5109933')
finally:
driver.quit()
if __name__ == "__main__":
main()
(Full disclosure: I maintain the explicit package, which is meant to simplify using explicit waits. You can replace it with direct waits and get the same affect. Simply pip install explicit to install)

How to get name of the default browser in windows using python? [duplicate]

My script runs a command every X seconds.
If a command is like "start www" -> opens a website in a default browser I want to be able to close the browser before next time the command gets executed.
This short part of a script below:
if "start www" in command:
time.sleep(interval - 1)
os.system("Taskkill /IM chrome.exe /F")
I want to be able to support firefox, ie, chrome and opera, and only close the browser that opened by URL.
For that I need to know which process to kill.
How can I use python to identify my os`s default browser in windows?
The solution is going to differ from OS to OS. On Windows, the default browser (i.e. the default handler for the http protocol) can be read from the registry at:
HKEY_CURRENT_USER\Software\Classes\http\shell\open\command\(Default)
Python has a module for dealing with the Windows registry, so you should be able to do:
from _winreg import HKEY_CURRENT_USER, OpenKey, QueryValue
# In Py3, this module is called winreg without the underscore
with OpenKey(HKEY_CURRENT_USER,
r"Software\Classes\http\shell\open\command") as key:
cmd = QueryValue(key, None)
You'll get back a command line string that has a %1 token in it where the URL to be opened should be inserted.
You should probably be using the subprocess module to handle launching the browser; you can retain the browser's process object and kill that exact instance of the browser instead of blindly killing all processes having the same executable name. If I already have my default browser open, I'm going to be pretty cheesed if you just kill it without warning. Of course, some browsers don't support multiple instances; the second instance just passes the URL to the existing process, so you may not be able to kill it anyway.
I would suggest this. Honestly Python should include this in the webbrowser module that unfortunately only does an open bla.html and that breaks anchors on the file:// protocol.
Calling the browser directly however works:
# Setting fallback value
browser_path = shutil.which('open')
osPlatform = platform.system()
if osPlatform == 'Windows':
# Find the default browser by interrogating the registry
try:
from winreg import HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, OpenKey, QueryValueEx
with OpenKey(HKEY_CURRENT_USER, r'SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice') as regkey:
# Get the user choice
browser_choice = QueryValueEx(regkey, 'ProgId')[0]
with OpenKey(HKEY_CLASSES_ROOT, r'{}\shell\open\command'.format(browser_choice)) as regkey:
# Get the application the user's choice refers to in the application registrations
browser_path_tuple = QueryValueEx(regkey, None)
# This is a bit sketchy and assumes that the path will always be in double quotes
browser_path = browser_path_tuple[0].split('"')[1]
except Exception:
log.error('Failed to look up default browser in system registry. Using fallback value.')

Categories

Resources