Prevent OS X from going to sleep with Python? - python

Is there a way to prevent a computer running OS X from going to sleep from within a Python script?

You can use the built-in caffeinate command.
subprocess.Popen('caffeinate')
This is how I use it:
import sys
import subprocess
if 'darwin' in sys.platform:
print('Running \'caffeinate\' on MacOSX to prevent the system from sleeping')
subprocess.Popen('caffeinate')

You can also run caffeinate in an external terminal window and leave it open to achieve what the OP wants.
open a terminal
type caffeinate
press Enter
Once you have done this, your Mac will stay awake for as long as you leave the Terminal running.
You can minimize or hide it, and your Mac will not go to sleep until you use the keyboard shortcut Ctrl+C to interrupt the command.
source

Since OS 10.6, you have to make use of the IOPMAssertion family of functions, available in Cocoa. This is really well explained there.
Then, you will have to call it from Python. I'm not sure that there're already specific bindings for Cocoa in Python, but you can call Objective-C functions. It is really well described here.

There is a Python utility that illustrates how to raise the required assertions in Python directly: https://github.com/minrk/appnope

Another alternative would be to run the below script with
python <location/of/my/script.py> <hour until I want the PC to be awake>
e.g.
python /Users/johndee/Downloads/keep_awake.py 18:30
The script, which is to be saved locally:
#!/usr/bin/env python3
import random
import sys
import time
from datetime import datetime
from tkinter import Tk
import pyautogui
CHECK_STATUS_ONCE_IN = 120
WAIT_FOR_POSITION_CHANGE = 10
def current_position():
tkinter = Tk()
return [tkinter.winfo_pointerx(), tkinter.winfo_pointery()]
def mouse_is_moving():
pos1 = current_position()
time.sleep(WAIT_FOR_POSITION_CHANGE)
pos2 = current_position()
return not pos1 == pos2
def keep_awake():
# Shake the mouse a lil bit
initial_x, initial_y = current_position()
try:
for _ in range(random.randint(1, 10)):
# Mouse
pyautogui.moveTo(random.randint(1, 1000), random.randint(1, 1000))
# Keys
pyautogui.press("shift")
# Restore controls
pyautogui.moveTo(initial_x, initial_y)
except pyautogui.FailSafeException as e:
print(e)
def inspect_activity_until(time_to_stop: datetime):
time_to_stop = datetime.now().replace(
hour=time_to_stop.hour, minute=time_to_stop.minute
)
while datetime.now() < time_to_stop:
if not mouse_is_moving():
keep_awake()
time.sleep(CHECK_STATUS_ONCE_IN)
print(f"Stopping at {datetime.now()}")
if __name__ == "__main__":
given_time = sys.argv[1]
date_time_obj = datetime.strptime(given_time, "%H:%M")
inspect_activity_until(date_time_obj)

Related

Python, how to execute a line of code without it stopping the rest of the code from executing?

first of all, im a beginner.
Want i want to accomplish is that music plays while the script is executing.
What it does right now it plays the music, waits until the music is over and then executes the rest of the code. That is not what i want. Here my Code:
import os
import subprocess
import multiprocessing
import threading
from playsound import playsound
CurrentPath = os.path.dirname(os.path.normpath(__file__))
os.chdir(CurrentPath)
def music():
Music = "Music.mp4"
#subprocess.run(["ffplay", "-nodisp", "-autoexit", "-hide_banner", Music])
playsound("Music.mp4")
def other_things():
print("Hello World")
#musicp = multiprocessing.Process(target=music())
#restp = multiprocessing.Process(target=other_things())
musicp = threading.Thread(target=music())
restp = threading.Thread(target=other_things())
restp.start()
musicp.start()
LIke you can see i even tried multithreading but it still waits until the music is over before it goes to the rest of the code.
Don't call the functions in the target parameter of the Thread function - delete the brackets to reference the function, not its return value
musicp = threading.Thread(target=music) # instead of music()
restp = threading.Thread(target=other_things) # instead of other_things()

Python console Fullscreen? Maybe using os.system?

I'm trying to figure out how to get my program to open in a fullscreen console window.
Is there any command that you can type within the command prompt to toggle fullscreen?
If so I'd imagine the code going something like:
from os import system
system("toggle.fullscreen")
{CODE HERE}
I understand mode con can be used, but that doesn't actually toggle it being maximized, which would be much more useful for me, thanks!
Here's a function to maximize the current console window. It uses ctypes to call WinAPI functions. First it calls GetLargestConsoleWindowSize in order to figure how big it can make the window, with the option to specify a number of lines that exceeds this in order to get a scrollback buffer. To do the work of resizing the screen buffer it simply calls mode.com via subprocess.check_call. Finally, it gets the console window handle via GetConsoleWindow and calls ShowWindow to maximize it.
import os
import ctypes
import msvcrt
import subprocess
from ctypes import wintypes
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
user32 = ctypes.WinDLL('user32', use_last_error=True)
SW_MAXIMIZE = 3
kernel32.GetConsoleWindow.restype = wintypes.HWND
kernel32.GetLargestConsoleWindowSize.restype = wintypes._COORD
kernel32.GetLargestConsoleWindowSize.argtypes = (wintypes.HANDLE,)
user32.ShowWindow.argtypes = (wintypes.HWND, ctypes.c_int)
def maximize_console(lines=None):
fd = os.open('CONOUT$', os.O_RDWR)
try:
hCon = msvcrt.get_osfhandle(fd)
max_size = kernel32.GetLargestConsoleWindowSize(hCon)
if max_size.X == 0 and max_size.Y == 0:
raise ctypes.WinError(ctypes.get_last_error())
finally:
os.close(fd)
cols = max_size.X
hWnd = kernel32.GetConsoleWindow()
if cols and hWnd:
if lines is None:
lines = max_size.Y
else:
lines = max(min(lines, 9999), max_size.Y)
subprocess.check_call('mode.com con cols={} lines={}'.format(
cols, lines))
user32.ShowWindow(hWnd, SW_MAXIMIZE)
You can use keyboard.press. Install with pip3 install keyboard if it is not installed.
Code:
import keyboard
keyboard.press('f11')
I found this awhile back on a different post and it works perfectly for console window maximization:
import win32gui, win32con
hwnd = win32gui.GetForegroundWindow()
win32gui.ShowWindow(hwnd, win32con.SW_MAXIMIZE)

How to make a messagebox auto close in several seconds by Python?

I already know how to make a Messagebox by Python:
import ctypes
ctypes.windll.user32.MessageBoxW(0, 'test', "Reminding", 0)
However, I want it to be closed by itself in several seconds after it shows up.
Is there any method to realize it?
Psuedo code:
def AutoCloseMessageBoxW(text, title, close_until_seconds)
I have found a lot of methods to realize this by other language such as C# and Java.
But I just can't find any method to realize it by Python.
import ctypes
import threading
import time
#ctypes.windll.user32.MessageBoxA(0, 'test', "Reminding", 0)
def worker(title,close_until_seconds):
time.sleep(close_until_seconds)
wd=ctypes.windll.user32.FindWindowA(0,title)
ctypes.windll.user32.SendMessageA(wd,0x0010,0,0)
return
def AutoCloseMessageBoxW(text, title, close_until_seconds):
t = threading.Thread(target=worker,args=(title,close_until_seconds))
t.start()
ctypes.windll.user32.MessageBoxA(0, text, title, 0)
AutoCloseMessageBoxW('112','TEST_CLOSE',3)
Use pyautogui
import pyautogui as py # pip install pyautogui
# It is automatically terminated after three seconds. If automatically ends, return "Timeout" returns.
def show_message():
res = py.confirm(text='Message...', buttons=['Yes', 'No'], timeout=3000)
print(res)

Python Serial Port with threading - freezing computer

Okay, time for another question/post...
So currently i am trying to develop a simple python program that has a webkit/ webpage view and a serial port interface.. Not that it should matter, but this is also running on a raspberry pi.
The following code works fine.. But it will freeze the system as soon as i uncomment the serial port line that you can see commented out.
The day has been long and this one for some reason has my brain fried.. Python is not my strongest point, but mind you this is just a quick test script for now... Yes i have used google and other resources...
#!/usr/bin/env python
import sys
import serial
import threading
import time
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
sURL = ""
sURL2 = ""
objSerial = serial.Serial(0)
def SerialLooper():
global objSerial
if objSerial.isOpen() == True:
print("is_responding")
#objSerial.write("is_responding")
time.sleep(10)
SerialLooper()
class TestCLASS(object):
def __init__(self):
global sURL
global sURL2
global objSerial
objSerial = serial.Serial(0)
sURL = "http://localhost/tester"
app = QApplication(sys.argv)
webMain = QWebView()
webMain.loadFinished.connect(self.load_finished)
webMain.load(QUrl(sURL))
webMain.show()
thread = threading.Thread(target=SerialLooper)
thread.start()
sys.exit(app.exec_())
def load_finished(boolNoErrors):
global sURL
print("Url - " + sURL)
#something here
#something else here
newObjClass = TestCLASS()
EDIT
Futher on this, it appears its not the multithreading but the serial.write()
It has been a while since I used serial, but IIRC it is not threadsafe (on Windows at least). You are opening the port in the main thread and performing a write in another thread. It's a bad practice anyway. You might also consider writing a simple single-threaded program to see if the serial port is actually working.
PS Your program structure could use some work. You only need one of the global statements (global objSerial), the rest do nothing. It would be better to get rid of that one, too.
And the recursive call to SerialLooper() will eventually fail when the recursion depth is exceeded; why not just use a while loop...
def SerialLooper():
while objSerial().isOpen(): # Drop the == True
# print something
# write to the port
# Sleep or do whatever

How to get the text cursor position in Windows?

Is it possible to get the overall cursor position in Windows using the standard Python libraries?
Using the standard ctypes library, this should yield the current on screen mouse coordinates without any third party modules:
from ctypes import windll, Structure, c_long, byref
class POINT(Structure):
_fields_ = [("x", c_long), ("y", c_long)]
def queryMousePosition():
pt = POINT()
windll.user32.GetCursorPos(byref(pt))
return { "x": pt.x, "y": pt.y}
pos = queryMousePosition()
print(pos)
I should mention that this code was taken from an example found here
So credit goes to Nullege.com for this solution.
win32gui.GetCursorPos(point)
This retrieves the cursor's position, in screen coordinates - point = (x,y)
flags, hcursor, (x,y) = win32gui.GetCursorInfo()
Retrieves information about the global cursor.
Links:
http://msdn.microsoft.com/en-us/library/ms648389(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms648390(VS.85).aspx
I am assuming that you would be using python win32 API bindings or pywin32.
You will not find such function in standard Python libraries, while this function is Windows specific. However if you use ActiveState Python, or just install win32api module to standard Python Windows installation you can use:
x, y = win32api.GetCursorPos()
I found a way to do it that doesn't depend on non-standard libraries!
Found this in Tkinter
self.winfo_pointerxy()
Using pyautogui
To install
pip install pyautogui
and to find the location of the mouse pointer
import pyautogui
print(pyautogui.position())
This will give the pixel location to which mouse pointer is at.
For Mac using native library:
import Quartz as q
q.NSEvent.mouseLocation()
#x and y individually
q.NSEvent.mouseLocation().x
q.NSEvent.mouseLocation().y
If the Quartz-wrapper is not installed:
python3 -m pip install -U pyobjc-framework-Quartz
(The question specify Windows, but a lot of Mac users come here because of the title)
It's possible, and not even that messy! Just use:
from ctypes import windll, wintypes, byref
def get_cursor_pos():
cursor = wintypes.POINT()
windll.user32.GetCursorPos(byref(cursor))
return (cursor.x, cursor.y)
The answer using pyautogui made me wonder how that module was doing it, so I looked and this is how.
This could be a possible code for your problem :
# Note you need to install PyAutoGUI for it to work
import pyautogui
w = pyautogui.position()
x_mouse = w.x
y_mouse = w.y
print(x_mouse, y_mouse)
Prerequisites
Install Tkinter. I've included the win32api for as a Windows-only solution.
Script
#!/usr/bin/env python
"""Get the current mouse position."""
import logging
import sys
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
level=logging.DEBUG,
stream=sys.stdout)
def get_mouse_position():
"""
Get the current position of the mouse.
Returns
-------
dict :
With keys 'x' and 'y'
"""
mouse_position = None
import sys
if sys.platform in ['linux', 'linux2']:
pass
elif sys.platform == 'Windows':
try:
import win32api
except ImportError:
logging.info("win32api not installed")
win32api = None
if win32api is not None:
x, y = win32api.GetCursorPos()
mouse_position = {'x': x, 'y': y}
elif sys.platform == 'Mac':
pass
else:
try:
import Tkinter # Tkinter could be supported by all systems
except ImportError:
logging.info("Tkinter not installed")
Tkinter = None
if Tkinter is not None:
p = Tkinter.Tk()
x, y = p.winfo_pointerxy()
mouse_position = {'x': x, 'y': y}
print("sys.platform={platform} is unknown. Please report."
.format(platform=sys.platform))
print(sys.version)
return mouse_position
print(get_mouse_position())
sudo add-apt-repository ppa:deadsnakes
sudo apt-get update
sudo apt-get install python3.5 python3.5-tk
# or 2.7, 3.6 etc
# sudo apt-get install python2.7 python2.7-tk
# mouse_position.py
import Tkinter
p=Tkinter.Tk()
print(p.winfo_pointerxy()
Or with one-liner from the command line:
python -c "import Tkinter; p=Tkinter.Tk(); print(p.winfo_pointerxy())"
(1377, 379)
I know this is an old thread, but have been having hard time figuring out how to do this with JUST the python standard libraries.
I think the code below will work to get the cursor position in a windows terminal:
import sys
import msvcrt
print('ABCDEF',end='')
sys.stdout.write("\x1b[6n")
sys.stdout.flush()
buffer = bytes()
while msvcrt.kbhit():
buffer += msvcrt.getch()
hex_loc = buffer.decode()
hex_loc = hex_loc.replace('\x1b[','').replace('R','')
token = hex_loc.split(';')
print(f' Row: {token[0]} Col: {token[1]}')
Use pygame
import pygame
mouse_pos = pygame.mouse.get_pos()
This returns the x and y position of the mouse.
See this website: https://www.pygame.org/docs/ref/mouse.html#pygame.mouse.set_pos
If you're doing automation and want to get coordinates of where to click, simplest and shortest approach would be:
import pyautogui
while True:
print(pyautogui.position())
This will track your mouse position and would keep on printing coordinates.

Categories

Resources