Unable to close browser using webbrowser module - python

Unable to close browser using python webbrowser.
I don't know how to close it.
Code is:
elif 'open chrome' in query:
Cpath = 'C:\\Users\\hi\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe'
os.startfile(Cpath)

You do not appear to using Python's webbrowser module to start one up, although even if you did it wouldn't help because the controller objects it creates don't support a close() method.
That's also true about the os.startfile() function you are using, and there's no option to wait for the application to close or to force it to do so.
Because of that, I suggest that you create an instance of the subprocess.Popen class to start the web-browser application, because if you did, you would then have the option of calling the terminate() (or kill()) method of the class instance to close it.

Related

How to use subprocess to run a program without a window showing?

I am using subprocess.call() to programatically launch a software on my PC (the Meta Trader platform for forex trading, to be exact). The call works fine, the terminal is launched properly, however I now want to improve the experience by removing the popping up Meta Trader window. I know that in web scraping it is possible to use a headless browser, enabling that scraping be done without an actual(ly visible) web browser window showing on the screen. I was wondering if there is some way to achieve the same functionality using subprocess.call() (or else).
There doesn't seem to be built-in support on other platforms, but it's possible on Windows by passing a STARTUPINFO instance to the Popen constructor.
The following example starts the Notepad editor in the background. Its window is hidden, but the program is running as the Task Manager would show. Pressing Ctrl+C stops the program and terminates the background process.
import subprocess
from time import sleep
process = subprocess.Popen(
'notepad',
startupinfo=subprocess.STARTUPINFO(
dwFlags=subprocess.STARTF_USESHOWWINDOW,
wShowWindow=subprocess.SW_HIDE,
),
)
try:
while process.poll() is None:
sleep(1)
except KeyboardInterrupt:
process.kill()
Note that this may not work for more complex applications that start their own subprocesses, such as the Chrome browser to name but one example. One may then have to go through the Windows API in order to hide the application windows after they were created.

AutoKey: Switch to last active application like Alt-Tab by using AutoKey

is it possible to send the alt+tab for switch to last window with AutoKey ?
i tried without success:
keyboard.send_keys("<alt>+<shift>+<tab>")
Or forward window:
keyboard.press_key('<alt>')
keyboard.press_key('<tab>')
keyboard.release_key('<tab>')
keyboard.release_key('<alt>')
Or backward window:
keyboard.press_key('<alt>')
keyboard.press_key('<shift>')
keyboard.press_key('<tab>')
keyboard.release_key('<tab>')
keyboard.release_key('<shift>')
keyboard.release_key('<alt>')
result: no error but only moves the tab count inside the editor.
TL;DR: Not directly with our API.
The AutoKey API talks directly to the current active window. So, sending events targeted at the desktop (DTE) will only work if the current active window recognizes them as such and either forwards them to the DTE or emulates what they do.
However, since AutoKey scripts are written in full Python 3, if you can figure out how to do it yourself in Python, AutoKey can run it for you. And, if some other solution is available, you can run it from within an AutoKey script using the subprocess module.
Autokey's Window class allows you to activate a window by name (via wmctrl), among other functionality. Something in that class may be what you're looking for.

How to refresh a browser tap after time.sleep in python

So this is what I'm using to open the browser
import webbrowser
import time
url = "http://google.com"
time = 5
def TestBrowse(url,time):
webbrowser.open(url)
time.sleep(time)
I want a function or method following time.sleep that will refresh the tab that the function opens. This is a module I'm just getting familiar with so I don't even know if its a better module or solution for this (or if at all possible)
Infact my main target was to be able to close the tab but I've been reading there is no way to do that, If this is false I would also love knowing how to do that. I've experimented with using os.system to kill the browser but os.system never seems to work inside a function (and It doesn't seem like a good idea anyway)
Maybe using selenium would be a better option for browser programing.
It accepts python scripts.
Also, you could try creating a wrapper web page with an embedded script that does the refreshing and/or exiting, though the browser might threat it as a cross-site scripting and limit the functionality of the URL you are trying to access. In any case to use that you would need to program in javascript rather than python.

How to open an application in Python, and then let the rest of the script run?

I have been trying to create a script which reloads a web browser called Midori if the internet flickers. But, it seems only to work if I open Midori through the CLI - otherwise, the program crashes after I reload it. I have decided that the best idea is thus to have the script open Midori through the subprocess module. So, I put this as one of the first arguments in my code:
import subprocess as sub
sub.call(["midori"])
The browser opens, but the rest of the program freezes until I quit Midori. I have tried to use threading, but it doesn't seem to work.
Is there any way to open an application through Python, and then let the rest of the script continue to run once said application has been opened?
From the docs:
Run the command described by args. Wait for command to complete, then return the returncode attribute.
(Emphasis added)
You can see this is the behaviour we should expect. To get around this, use subprocess.Popen instead. This will not block in the same way:
from subprocess import Popen
midori_process = Popen(["midori"])

Prevent a console app from closing when not invoked from an existing terminal?

There are many variants on this kind of question. However I am specifically after a way to prevent a console application in Python from closing when it is not invoked from a terminal (or other console, as it may be called on Windows). An example where this could occur is double clicking a .py file from the Windows explorer.
Typically I use something like the following code snippet, but it has the unfortunate side effect of operating even if the application is invoked from an existing terminal:
def press_any_key():
if os.name == "nt":
os.system("pause")
atexit.register(press_any_key)
It's also making the assumption that all Windows users are invoking the application from the Windows "shell", and that only Windows users can execute the program from a location other than an existing terminal.
Is there a (preferably cross platform) way to detect if my application has been invoked from a terminal, and/or whether it is necessary to provide a "press any key..." functionality for the currently running instance? Note that resorting to batch, bash or any other "wrapper process" workarounds are highly undesirable.
Update0
Using Alex Martelli's answer below, I've produced this function:
def register_pause_before_closing_console():
import atexit, os
if os.name == 'nt':
from win32api import GetConsoleTitle
if not GetConsoleTitle().startswith(os.environ["COMSPEC"]):
atexit.register(lambda: os.system("pause"))
if __name__ == '__main__':
register_pause_before_closing_console()
If other suitable answers arise, I'll append more code for other platforms and desktop environments.
Update1
In the vein of using pywin32, I've produced this function, which improves on the one above, using the accepted answer. The commented out code is an alternative implementation as originating in Update0. If using pywin32 is not an option, follow the link in the accepted answer. Pause or getch() to taste.
def _current_process_owns_console():
#import os, win32api
#return not win32api.GetConsoleTitle().startswith(os.environ["COMSPEC"])
import win32console, win32process
conswnd = win32console.GetConsoleWindow()
wndpid = win32process.GetWindowThreadProcessId(conswnd)[1]
curpid = win32process.GetCurrentProcessId()
return curpid == wndpid
def register_pause_before_closing_console():
import atexit, os, pdb
if os.name == 'nt':
if _current_process_owns_console():
atexit.register(lambda: os.system("pause"))
if __name__ == '__main__':
register_pause_before_closing_console()
First, an attempt to disuade you from clever hacks. It's perfectly appropriate to have a seperate shortcut designed to be run from Explorer that does slightly different things (like holding the console open) from the script to be used from the commandline. As Alex has already pointed out, this is not an issue on nix, and the right thing to do there is always exit cleanly or your users will complain.
If you still want a workaround, here's code to detect when the console needs to be prevented from closing that's reasonably clean. Requires Windows 2000 or later, the logic is contained in this function:
def owns_console():
wnd = GetConsoleWindow()
if wnd is None:
return False
return GetCurrentProcessId() == GetWindowThreadProcessId(wnd)
Basically, it gets the PIDs of the process that owns the console Python is using, and of our process. If they are the same, then when we exit the console will go away, so it needs to be held open. If they are different, or if there's no console attached, Python should exit normally.
On Unix, sys.stdin.isatty() reliably tells you whether standard input is coming from a terminal-like device (or is otherwise redirected), and similarly for the same method on sys.stdout and sys.stderr -- so you can use those calls to determine whether the application is being executed interactively or in some non-interactive environment (such as a cron job). Exactly how you want to use them depends on what you want to do if (for example) both standard input and output are redirected to a non-terminal but standard error is going to a terminal -- consider each of the 8 possibilities, from all of them redirected to non-terminals to none of them, and decide what you want to do in each case.
On Windows the situation is different since executing a .py file (as opposed to a .pyw file) will create a new transient console (there's no exactly equivalent situation in Unix); I assume that's the case you want to deal with? (Or is it just about redirection of standard I/O streams to files, which is possible in Windows roughly just like in Unix?). I think the best approach in Windows might be to use win32api.SetConsoleCtrlHandler to set a handler for such events as CTRL_CLOSE_EVENT -- this way the handler should be invoked (in this case, when the console closes) if there is a console for the process, but not otherwise. Or, if all you care about is whether a console is there at all or not (and prefer to handle things your way otherwise), try calling win32api.GetConsoleTitle in the try leg of a try/except statement -- it will generate an exception (which you catch and respond to by setting a boolean variable of yours to False) if there's no console, and just work (in which case you set that boolean variable to True) if there is a console.

Categories