PYTHON rumps program stops responding after subprocess calls another script - python-3.x

I am currently working on a project that contains many system tray utilities on mac osx, one of these utilities is a 'fake friend soundboard' where I am to enable the user to click on the module then select as example "Discord Ping x1" and the program playback a soundfile of the ping.
Im using RUMPS which enables me to add menus to the system tray however when trying to use libraries to play sounds directly through upon the #rumps.clicked, nothing seems to happen
Instead I've programmed it to run another script that can easily play the sound inside another folder containing all the sounds.
When running the script and clicking a sound, it plays the sound exactly as intended,
but then the program stops responding...
Is this something I'm doing wrong with my code or is there another way i could play the sound using this library?
Heres the code:
import rumps
import subprocess
class sound(rumps.App):
def __init__(self):
super(sound, self).__init__("🔊")
self.menu = ["Fake friend soundboard",
None,
"Discord Sounds:",
"Ping x1",
"Incoming Call",
"Enter Call",
"Leave Call",
"Mute",
"Deafen",
None,
"Skype Sounds:",
"Incoming Call",
None,
"Random:",
"okbuddyretard",
None]
#rumps.clicked("Ping x1")
def about(sender):
subprocess.run("python3 soundboard/discord_pingx1.py", shell=True)
if __name__ == "__main__":
sound().run()
In the soundboard folder there is the sounds folder containing the discord folder containing **
discord_ping.wav
The soundboard folder also hold the discordd_pingx1.py script which is below.
import pyglet
def sound():
sound = pyglet.resource.media('sounds/discord/discord_ping.wav', streaming=False)
sound.play()
pyglet.app.run()
sound()
after running my main.py (opens all the modules)
and clicking the sound tab and then clicking the button set to make the sound,
it plays, but then stops responding.
Any help at all would be much appreciated.

I highly recommend avoiding the insert of subprocess or sys-calls inside of a Python script that executes Objective-C code. This leads to Aborts and Traps. Instead, refer to Apple's APIs and utilize AppleScript (osascript).
Here is a better implementation that calls a script to call your script from osascript:
exec.py
import platform
import subprocess, sys, os
applescript = '''\
do shell script "bash /path/to/file/myShellScript.sh"\
'''
# parse and stdout
args = [item for x in [("-e",l.strip()) for l in applescript.split('\n') if l.strip() != ''] for item in x]
proc = subprocess.Popen(["osascript"] + args ,stdout=subprocess.PIPE )
progname = proc.stdout.read().strip()
sys.stdout.write(str(progname))
The parser takes the string with the osascript in it and parses it for a stdout write. Stdout writes are very safe, considering they are handling data from the same thread.
/path/to/file/myShellScript.sh (add the shebang on line 1 as well)
#!/bin/bash
python3 soundboard/discord_pingx1.py
This 100% handles your problem without causing subprocess errors. If you get hung with subprocess, your computer will continue running Python3. If the Application doesn't stop freezing, exit the app by cmd+Space and typing Activity Monitor. Then, find Python3 by cmd+f and typing python3. Click it and press Quit in the top left corner (the X or stop-light symbol).

Related

Beginner Python Project - My function is skipping, what is causing this?

as the title says I'm a beginner with Python. I have started to work on what I thought first was a simple enough script for scanning a folder and printing the names of each subdirectory to a CMD prompt.
However, I've run into an issue where the function in the code below does not execute. I suspect it's to do with Windows permissions which is why I've added in the is_admin(): function.
My question is, what is it that is causing the function to skip? and what is the proper way to achieve what it is I am trying to do?
Any and all help is appreciated and if anyone could point me in the direction for learning more about Python and the Windows OS technical side for programmers would be doing me a huge favor.
Thanks in advance :)
import os, sys, ctypes
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
if is_admin():
rootdir = 'C:/Windows'
def listdirs(rootdir):
for file in os.listdir(rootdir):
d = os.path.join(rootdir, file)
if os.path.isdir(d):
print(d)
listdirs(d)
listdirs(rootdir)
else:
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv\[1:\]), None, 1)
input('Press any key to continue...')
Expecting the program to:
Produce an output of all the subdirectories of a folder printed to a CMD prompt window and have the window stay open when the program has finished executing each line of code. The Window should remain open until the user is finished with it. The Windows UAC should prompt asking the user if they wish to run as admin, if the user is already an admin then it should skip this and proceed to run the program.

pywinauto possible to keep application alive if I exit python script?

app = Application(backend="uia").start("program.exe")
I am using pywinauto to do some tasks indefinitely. However, occasionally, I need to restart the script for some external reasons. When this happens, I would like to keep the created applications open. How can I do this? I noticed if the python script errors out, the applications will stay open. But if I exit the script manually, the windows will close. So there must be some way to accomplish this.
I think pywinauto's Application.start cannot do the work. You can try:
pid = os.spawnl(os.P_NOWAIT, "program.exe")
app = Application().connect(process=pid)
os.spawnl is considered deprecated. Use subprocess module.
Combining the answer in Run a program from python, and have it continue to run after the script is killed and pywinauto official doc, you can do this:
subprocess.Popen(
['your_program', 'with args'],
# These will make sure the desktop program will alive even when shell session terminates.
creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP, shell=True
)
desktop = Desktop(backend="uia")
main_win = desktop.window(title="program's window title", control_type="Window")
Why not use system command:
#Use multiple thread to avoid block of system function
import _thread as qd
import os
qd.start_new_thread(os.system,('notepad',))
from pywinauto import Application
#connect pywinauto with application via title regular expression
win=Application(backend='uia').connect(title_re='.*Notepad.*')
Then you use pywinauto to connect application via title?

Running console window in background for GUI using tkinter on Windows 10

So I have this GUI that I made with tkinter and everything works well. What it does is connects to servers and sends commands for both Linux or Windows. I went ahead and used pyinstaller to create a windowed GUI without console and when I try to uses a specific function for sending Windows commands it will fail. If I create the GUI with a console that pops up before the GUI, it works like a charm. What I'm trying to figure out is how to get my GUI to work with the console being invisible to the user.
The part of my code that has the issue revolves around subprocess. To spare you all from the 400+ lines of code I wrote, I'm providing the specific code that has issues. Here is the snippet:
def rcmd_in(server):
import subprocess as sp
for i in command_list:
result = sp.run(['C:/"Path to executable"/rcmd.exe', '\\\\' + server, i],
universal_newlines=True, stdout=sp.PIPE, stderr=sp.STDOUT)
print(result.stdout)
The argument 'server' is passed from another function that calls to 'rcmd_in' and 'command_list' is a mutable list created in the root of the code, accessible for all functions.
Now, I have done my due diligence. I scoured multiple searches and came up with an edit to my code that makes an attempt to run my code with that console invisible, found using info from this link: recipe-subprocess. Here is what the edit looks like:
def rcmd_in(server):
import subprocess as sp
import os, os.path
si = sp.STARTUPINFO()
si.dwFlags |= sp.STARTF_USESHOWWINDOW
for i in command_list:
result = sp.run(['C:/"Path to executable"/rcmd.exe', '\\\\' + server, i],
universal_newlines=True, stdin=sp.PIPE, stdout=sp.PIPE,
stderr=sp.STDOUT, startupinfo=si, env=os.environ)
print(result.stdout)
The the problem I have now is when it runs an error of "Error:8 - Internal error -109" pops up. Let me add I tried using functions 'call()', 'Popen()', and others but only 'run()' seems to work.
I've reached a point where my brain hurts and I can use some help. Any suggestions? As always I am forever great full for anyone's help. Thanks in advance!
I figured it out and it only took me 5 days! :D
Looks like the reason the function would fail falls on how Windows handles stdin. I found a post that helped me edit my code to work with pyinstaller -w (--noconsole). Here is the updated code:
def rcmd_in(server):
import subprocess as sp
si = sp.STARTUPINFO()
si.dwFlags |= sp.STARTF_USESHOWWINDOW
for i in command_list:
result = sp.Popen(['C:/"Path to executable"/rcmd.exe', '\\\\' + server, i],
universal_newlines=True, stdin=sp.PIPE, stdout=sp.PIPE,
stderr=sp.PIPE, startupinfo=si)
print(result.stdout.read())
Note the change of functions 'run()' to 'Popen()'. The 'run()' function will not work with the print statement at the end. Also, for those of you who are curious the 'si' variable I created is preventing 'subprocess' from opening a console when being ran while using a GUI. I hope this will become useful to someone struggling with this. Cheers

How to execute another Python script (Server) but keep the current script running at the same time

I'm making a multiplayer game on Python3. In my main menu screen, when the player clicks play I want the maingame subroutine to run, but also a completely separate file (Server.py) to run in another window parallel to it. Right now I have to open Server.py separately and then the main game file, but I want to be able to open both from the main menu.
I've tried this:
import os
import subprocess
If user_selection == "start":
command="Server1.py"
os.system(command)
subprocess.Popen(command)
main_game()
The command, os and subprocess parts are supposed to run the server1.py file (which it does). But then it proceeds to run main_game() in the same window so it stops the server and runs the game instead. I've tried using the subprocess command twice (one for server.py and other for main_game.py) but it didn't work. Is there a way when the player clicks "run game" form the main menu screen, the server file executes in a second window and the first window goes from the main menu to the main_game subroutine?
note: both files are in the same directory.
Thanks :)
From the info provided, it seems that concurrent.futures would be the right way to run structure your code. From the python docs
with ThreadPoolExecutor(max_workers=4) as e:
e.submit(shutil.copy, 'src1.txt', 'dest1.txt')
e.submit(shutil.copy, 'src2.txt', 'dest2.txt')
e.submit(shutil.copy, 'src3.txt', 'dest3.txt')
e.submit(shutil.copy, 'src4.txt', 'dest4.txt')
The code above will copy all of the files simultaneously.
For your code, you would submit both your client and your server to the ThreadPoolExecutor.

I want to embed python console in my tkinter window.. How can i do it?

I am making a text editor and want to add a feature of IDLE in my app. So i want an frame with python IDLE embedded in it with all menus and features which original python IDLE gives.
I looked in source of idle lib but cannot find a solution.
try:
import idlelib.pyshell
except ImportError:
# IDLE is not installed, but maybe pyshell is on sys.path:
from . import pyshell
import os
idledir = os.path.dirname(os.path.abspath(pyshell.__file__))
if idledir != os.getcwd():
# We're not in the IDLE directory, help the subprocess find run.py
pypath = os.environ.get('PYTHONPATH', '')
if pypath:
os.environ['PYTHONPATH'] = pypath + ':' + idledir
else:
os.environ['PYTHONPATH'] = idledir
pyshell.main()
else:
idlelib.pyshell.main()
This code is of pyshell.pyw found under idlelib folder in all python install
I searched the idle.pyw and found that it uses a program pyshell which is real shell. So how can i embed it.
I want a Tkinter frame with python IDLE shell embedded in it.Please give the code. Thanks in advance.
idlelib implements IDLE. While you are free to use it otherwise, it is private in the sense that code and interfaces can change in any release without the usual back-compatibility constraints. Import and use idlelib modules at your own rish.
Currently, a Shell window is a Toplevel with a Menu and a Frame. The latter has a Text and vertical Scrollbar. It is not possible to visually embed a Toplevel within a frame (or within another Toplevel or root = Tk()). top = Toplevel(myframe) works, but top cannot be placed, packed, or gridded within myframe.
I hope in the future to refactor editor.py and pyshell.py so as to separate the window with menu from the frame with scrollable text. The result should include embeddable EditorFrame and ShellFrame classes that have parent as an arguments. But that is in the future.
Currently, one can run IDLE from within python with import idlelib.idle. However, because this runs mainloop() (on its own root), it blocks and does not finish until all IDLE windows are closed. This may not be what one wants.
If having Shell run in a separate window is acceptable, one could extract from python.main the 10-20 lines needed to just run Shell. Some experimentation would be needed. If the main app uses tkinter, this function should take the app's root as an argument and not call mainloop().
Tcl having Tkcon.tcl . when each thread source (means run/exec) the Tkcon.tcl
each thread will pop up a Tk shell/Tk console/tkcon.tcl very good idea for debug. and print message individually by thread.
Python having idle.py ... and how to use it ? still finding out the example .
The are same Tk base . why can't find an suitable example? so far ... keep finding...

Resources