Python run an outside python program - python

Im trying to lock the volume of the sonos using SoCo in a webapp. I need to run a separate script to do this. So when the user presses the lock button it runs a loop constantly setting the volume to the value until the program gets called or toggled stopping it.
I need this done in a different script as if its in the main code i'm unable to get any user input to unlock it.
#app.route("/lock")
def lock():
run(togglelock.py)
return "ok"
#togglelock.py
toggle("F","T")
sound1 = (sonos.volume)
if toggle == "T":
sonos1.volume = sound1
else:
break

As long as the other python file is in the same directory, you can simply import it when you want to run it.
def lock():
import togglelock
return "ok"
#do more stuff....

Related

Sleep function OBSpython and OBSlua

Lua:
obs = obslua
local clock = os.clock
function sleep(n)-- seconds
local t0 = clock()
while clock() - t0 <= n do end
end
function script_description()
return "auto restart replay buffer"
end
function refresh_button()
print('hello')
print('world')
sleep(3)
return nil
end
function script_properties()
local props = obs.obs_properties_create()
local button = obs.obs_properties_add_button(props, "button", "Refresh", refresh_button)
return props
end
Python:
import obspython as obs
import time
import sys
test_hotkey = obs.OBS_INVALID_HOTKEY_ID
def refresh_pressed(props, prop):
print("hello")
time.sleep(4)
print("world")
obs.obs_frontend_replay_buffer_start()
def script_properties():
props = obs.obs_properties_create()
obs.obs_properties_add_button(props, "button", "Refresh", refresh_pressed)
return props
def script_description():
return "stop replay buffer on save and restart it after some time."
The sleep function doesnt work as intended in either of the language. It does work normally if i run it in vscode but not when i run it inside OBS. So, I assume it's OBS's fault. Either way im gonna need someone who has experience with OBS Scripting to help me out with making a script that automatically stops Replay Buffer and starts it after few sec ( 2sec ). Basically clearing the replay buffer making it work exactly like Nvidia's Instant Replay.
Okay, so I am trying to make a script where upon pressing the SAVE REPLAY hotkey the script waits for a few seconds then stops the replay and starts it again after a few seconds. To achieve that I am first trying to make the sleep command work but for some reason, it is giving priority to the sleep command regardless of the order it is in ( in python and Lua). I am new to scripting so I'm just making use of docs and everything I can find. If the script to this already exists or if any one of you is kind enough to script it for me that would be really nice of you. Also, do explain to me why the sleep command is doing that. I figured it's only when I'm using it in obs, otherwise, the sleep command works as intended. The drawback to this is that obs.obs_frontend_replay_buffer_start() obs.obs_frontend_replay_buffer_stop() both commands are run at the same time by OBS so only one command really works ( if replay buffer is active then it stops and vice versa ) it doesn't really restart which it should do

Break loop using hotkey

There are hundreds of similar questions but none of them appear to be a solution in my case.
My code is shaped in this way
def iterative_func():
# do things
while True:
iterative_func()
Then I would like it to stop when I press a hotkey let's say 'ctrl+k'.
I tried pynput but the listener is not applicable since it waits for an Input and the rest of the script (iterative_func()) won't run, in my case the script should continuously run until I press some hotkey.
Also the solution
while True:
try:
iterative_func()
except KeyboardInterrupt:
break
doesn't work for me (I don't know why, but maybe it's because I'm running VSCode), anyway it's not code I want to implement because the script will be deployed as a .exe file.
PS.
I cannot import Key and Controller from pynput, it prompts an error and I have no clue on how to fix this so also solutions using these should be avoided.
I tried pynput but the listener is not applicable since it waits for
an Input and the rest of the script (iterative_func()) won't run
I can shed some light on how to overcome this problem, which made you optout pynput. See the below approach:
from pynput import keyboard
running = True # flag on loop runs
def stop_run(): # function to stop the program
global running
running = False
# register a hotkey, and call stop_run() when it is pressed
with keyboard.GlobalHotKeys({'<ctrl>+k': stop_run}) as h:
while running:
print("Running ... ")
This will run your code and wait for hotkey to stop the loop by a flag.

Using Rainmeter with Python

So I have designed a layout in Rainmeter which serves as a GUI for my Voice Assistant program. Now, I want to integrate the running of Rainmeter with Python. For example, if an user already has a Rainmeter layout loaded in his/her system, then running my script will automatically override his/her layout and activate my Layout unless he/she manually changes it back to his/her own layout. This process would continue whenever my script is run. It basically goes like this: The user runs the script, it checks whether any other skin is loaded or not (Assuming that Rainmeter is installed on the system). If any other skin is loaded, it overrides the skin with my one else it bypasses the override function and directly loads my skin.
I have no idea on how to achieve this thing. I have successfully written the lines to start and exit rainmeter with python but I don't know anything about how to load the layouts! Please help!
Here is the script I have written to start and exit Rainmeter:
import os
trigger = input()
if trigger == "y":
try:
os.startfile("C:\Program Files\Rainmeter\Rainmeter.exe")
print("Rainmeter started successfully")
except:
print("There was an error")
trigger = input()
if trigger == "exit":
try:
os.system("taskkill /f /im Rainmeter.exe")
print("Rainmeter closed successfully")
except:
print("There was an error")
You can use the following code to load a Rainmeter Layout:
import subprocess
subprocess.call(["C:\Program Files\Rainmeter\Rainmeter.exe", "!LoadLayout", "abcd"])
Here we are using rainmeter bangs to load the layout. Change abcd with name of your layout.

How to interrupt a program while it's running?

I wrote a program that reads a text file and runs an .exe for every line in the text file. This results in opening a new command line window for every time i run the .exe. The windows do close on their own once the current task is finished, but the problem is as follows:
If i have 100 lines in the text file, this means that i call the .exe file 100 times. My problem with that is if i want to cancel the run after it already started, i have to click on the red "X" to close every window one after the another.
What i am trying to do is have some sort of a command interrupt the running program and either close all upcoming windows or just stop the for loop from running.
Is it possible to write into the console a command to interrupt the current running code?
Would it be better to use some sort of a key event listener? If so, are there any built-in key listeners in Python? I can't seem to find any. Does that mean that i have to install Pygame just so i can use a key event listener?
Maybe i should try to listen to the command line and detect an exit code on one of the windows that i manually close and that way end the for loop?
There are a few ways you could go about this. But pretty much you have one main issue - you need some sort of flag that can be switched such that the code will know it must stop. For instance, if the code is working in a while-loop, it should check at the start of this loop if the flag is valid, or if the flag is telling the loop to stop...
while flag:
# do code
There are a few ways to implement this flagging like operation for your needs. I will discuss the threading option. First, you need to understand how threading works, and then you need to mold your script such that instead of "running an executable" for each line of the text file, you would read the text file, and put all the lines into a queue, then you would have a few threads that read from that queue, and perform the desired action (like running an executable) but instead of running an external executable, you should mimick this with Python, this thread should be a daemon thread.. and it should have a main loop which checks if a flag that exists in the parent thread is turned on...
Below is an example:
from threading import Thread
from Queue import Queue
import sys
import time
class Performer():
def __init__(self):
self.active = False
self.queue = Queue()
def action(self, line):
pass # your code should be here
def operate(self, text_file, threads=5):
with open(text_file) as f:
for line in f:
self.queue.put(line)
self.active = True
thread_pool = []
for i in range(threads):
t = Thread(target=self.__thread, name=('worker-%d' % i))
t.daemon = True
t.start()
thread_pool.append(t)
while self.active:
try:
if self.queue.empty():
break
except KeyboardInterrupt:
self.active = False
sys.exit('user + keyboard = byebye')
else:
time.sleep(1)
def __thread(self):
while self.active:
if not self.queue.empty():
try:
self.action(self.queue.get())
except Exception:
pass # do something here

Pygtk StatusIcon not loading?

I'm currently working on a small script that needs to use gtk.StatusIcon(). For some reason, I'm getting some weird behavior with it. If I go into the python interactive shell and type:
>> import gtk
>> statusIcon = gtk.status_icon_new_from_file("img/lin_idle.png")
Pygtk does exactly what it should do, and shows an icon (lin_idle.png) in the system tray:
However, if I try to do the same task in my script:
def gtkInit(self):
self.statusIcon = gtk.status_icon_new_from_file("img/lin_idle.png")
When gtkInit() gets called, I see this instead:
I made I ran the script in the same working directory as the interactive python shell, so I'm pretty sure it's finding the image, so I'm stumped... Any ideas anyone? Thanks in advance.
Update: For some reason or another, after calling gtk.status_icon_new_from_file() a few times in the script, it does eventually create the icon, but this issue still remains unfortunately. Does anyone at all have any ideas as to what could be going wrong?
As requested: Here's the full script. This is actually an application that I'm in the very early stages of making, but it does work at the moment if you get it setup correctly, so feel free to play around with it if you want (and also help me!), you just need to get an imgur developer key and put it in linup_control.py
Linup.py
#
# Linup - A dropbox alternative for Linux!
# Written by Nakedsteve
# Released under the MIT License
#
import os
import time
import ConfigParser
from linup_control import Linup
cfg = ConfigParser.RawConfigParser()
# See if we have a .linuprc file
home = os.path.expanduser("~")
if not os.path.exists(home+"/.linuprc"):
# Nope, so let's make one
cfg.add_section("paths")
cfg.set("paths","watch_path", home+"/Desktop/screenshot1.png")
# Now write it to the file
with open(home+"/.linuprc","wb") as configfile:
cfg.write(configfile)
else:
cfg.read(home+"/.linuprc")
linup = Linup()
# Create the GUI (status icon, menus, etc.)
linup.gtkInit()
# Enter the main loop, where we check to see if there's a shot to upload
# every 1 second
path = cfg.get("paths","watch_path")
while 1:
if(os.path.exists(path)):
linup.uploadImage(path)
url = linup.getURL()
linup.toClipboard(url)
linup.json = ""
print "Screenshot uploaded!"
os.remove(path)
else:
# If you're wondering why I'm using time.sleep()
# it's because I found that without it, my CPU remained
# at 50% at all times while running linup. If you have a better
# method for doing this, please contact me about it (I'm relatively new at python)
time.sleep(1)
linup_control.py
import gtk
import json
import time
import pycurl
import os
class Linup:
def __init__(self):
self.json = ""
def uploadImage(self, path):
# Set the status icon to busy
self.statusIcon.set_from_file("img/lin_busy.png")
# Create new pycurl instance
cu = pycurl.Curl()
# Set the POST variables to the image and dev key
vals = [
("key","*************"),
("image", (cu.FORM_FILE, path))
]
# Set the URL to send to
cu.setopt(cu.URL, "http://imgur.com/api/upload.json")
# This lets us get the json returned by imgur
cu.setopt(cu.WRITEFUNCTION, self.resp_callback)
cu.setopt(cu.HTTPPOST, vals)
# Do eet!
cu.perform()
cu.close()
# Set the status icon to done...
self.statusIcon.set_from_file("img/lin_done.png")
# Wait 3 seconds
time.sleep(3)
# Set the icon to idle
self.statusIcon.set_from_file("img/lin_idle.png")
# Used for getting the response json from imgur
def resp_callback(self, buff):
self.json += buff
# Extracts the image URL from the json data
def getURL(self):
js = json.loads(self.json)
return js['rsp']['image']['original_image']
# Inserts the text variable into the clipboard
def toClipboard(self, text):
cb = gtk.Clipboard()
cb.set_text(text)
cb.store()
# Initiates the GUI elements of Linup
def gtkInit(self):
self.statusIcon = gtk.StatusIcon()
self.statusIcon.set_from_file("img/lin_idle.png")
You need to call the gtk.main function like qba said, however the correct way to call a function every N milliseconds is to use the gobject.timeout_add function. In most cases you would want to have anything that could tie up the gui in a separate thread, however in your case where you just have an icon you don't need to. Unless you are planning on making the StatusIcon have a menu. Here is the part of Linup.py that I changed:
# Enter the main loop, where we check to see if there's a shot to upload
# every 1 second
path = cfg.get("paths","watch_path")
def check_for_new():
if(os.path.exists(path)):
linup.uploadImage(path)
url = linup.getURL()
linup.toClipboard(url)
linup.json = ""
print "Screenshot uploaded!"
os.remove(path)
# Return True to keep calling this function, False to stop.
return True
if __name__ == "__main__":
gobject.timeout_add(1000, check_for_new)
gtk.main()
You will have to import gobject somewhere too.
I don't know for sure if this works because I can't get pycurl installed.
EDIT: In linup_control.py, I would try changing
# Wait 3 seconds
time.sleep(3)
# Set the icon to idle
self.statusIcon.set_from_file("img/lin_idle.png")
to
gobject.timeout_add(3000, self.statusIcon.set_from_file, "img/lin_idle.png")
You made two mistakes. One is important one is not.
At first if you want to use stock icon use .set_from_stock( stock_id ) method. If you want to use your own icon then the .set_from_file(/path/to/img.png) is ok.
The other think witch is the probably the main problem is that when you write gtk application you have to call gtk.main() function. This is main gtk loop where all signal handling/window drawing and all other gtk stuff is done. If you don't do this, simply your icon is not drawing.
The solution in your case is to make two threads - one for gui, second for your app. In the first one you simply call gtk.main(). In second you put your main program loop. Of course when you call python program you have one thread already started:P
If you aren't familiar whit threads there is other solution. Gtk have function which calls function specified by you with some delay:
def call_me:
print "Hello World!"
gtk.timeout_add( 1000 , call_me )
gtk.timeout_add( 1000 , call_me )
gtk.main()
But it seems to be deprecated now. Probably they have made a better solution.

Categories

Resources