I am beginner in Python, ZMQ,networking or even coding in general, so please pardon my mistakes.
I am trying to send instructions to open notepad.exe from my desktop to my laptop like this:
MAIN SERVER
import zmq
import subprocess
try:
raw_input
except NameError:
raw_input = input #for python 3
#This will handle all the sockets we will open on the mainServer
context = zmq.Context()
#Socket 1 - Using for instructions
instructions = context.socket(zmq.PUSH)
instructions.bind("tcp://*:5555")
#Socket 2 - Using for end of finished instructions
#doneWork = context.socket(zmq.PULL)
#instructions.bind("tcp://*:5556")
#Now we will press enter when the workers are ready
print("Press Enter when you want to send the instructions. Make sure test devices are ready")
_=raw_input()
print ("Sending tasks to test device. . .")
instruction_One= "subprocess.call(['C:\notepad.exe'])"
instructions.send_string('%s' %instruction_One)
and
CLIENT
import zmq
import sys
context = zmq.Context()
instructions = context.socket(zmq.PULL)
instructions.connect("tcp://192.168.0.12:5555")
while True:
instruction_One=instructions.recv()
string_of_instruction = instruction_One.decode("utf-8")
sys.std.out.write(string_of_instruction)
sys.std.out.flush()
I am sending the instructions in terms of string which encoded into binary through the socket. But on the client side (laptop), whatever I am fetching cannot be executed through command line. What is the stupid mistake I am making?
I found out the fix.
instead of sys, I have used subprocess.
subprocess(command, shell=True)
Thanks
Related
I have a discord.py bot that runs on both Windows and Linux. It's a pretty normal bot that displays messages, has commands etc. But I also added reading text files in background to send them as messages in the discord later.
Apparenty I messed something up with asyncio and on Linux some people have lots of empty subprocesses that just sit there and do nothing. Bot works okay for them though.
I asked this question in the Discord API server and was told that discord.py doesn't cause this so the issue is somewhere in my code, which is quite possible since I'm not a pro in Python and getting async stuff to work cross-platform was hard.
What causes my problem and how to solve it?
import os, sys, math, re, time, threading, asyncio, signal, json, discord, psutil
from pathlib import Path
from mcrcon import MCRcon
from discord.ext import commands
# ..Lots of code..
async def update():
while runApp:
try:
# Collect data for bot to display
await attemptReading()
await asyncio.sleep(settings['update-interval'])
except asyncio.CancelledError: # Never occurs for some reason
break
print("'update' task and event loop stopped")
asyncio.get_event_loop().stop()
def ask_exit():
print("Stop tasks..")
for task in asyncio.Task.all_tasks():
task.cancel()
loop = asyncio.get_event_loop()
updateTask = loop.create_task(update())
# Run bot
print("Ctrl+C to stop the bot")
try:
loop.run_until_complete(bot.start(settings['token']))
except KeyboardInterrupt:
print("Shutting down..")
loop.run_until_complete(bot.logout())
botIsReady = False
runApp = False
print("Cancel tasks")
# cancel all tasks
try:
for sig in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(sig, ask_exit)
except NotImplementedError: # Windows
pass
loop.run_forever()
finally:
print("Shutted down")
loop.close()
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).
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
I am trying to write a shell that needs to run socket connections on a seperate thread. On my testings, when print() is used while cmd.Cmd.cmdloop() waiting for input, the print is displaying wrong.
from core.shell import Shell
import time
import threading
def test(shell):
time.sleep(2)
shell.write('Doing test')
if __name__ == '__main__':
shell = Shell(None, None)
testThrd = threading.Thread(target=test, args=(shell,))
testThrd.start()
shell.cmdloop()
When the above command runs, here is what happens:
python test.py
Welcome to Test shell. Type help or ? to list commands.
>>asd
*** Unknown syntax: asd
>>[17:59:25] Doing test
As you can see, printing from another threads add output after prompt >> not in a new line. How can I do it so that it appears in a new line and prompt appears?
What you can do, is redirect stdout from your core.shell.Shell to a file like object such as StringIO. You would also redirect the output from your thread into a different file like object.
Now, you can have some third thread read both of these objects and print them out in whatever fashion you want.
You said core.shell.Shell inherits from cmd.Cmd, which allows redirection as a parameter to the constructor:
import io
import time
import threading
from core.shell import Shell
def test(output_obj):
time.sleep(2)
print('Doing test', file=output_obj)
cmd_output = io.StringIO()
thr_output = io.StringIO()
shell = Shell(stdout=cmd_output)
testThrd = threading.Thread(target=test, args=(thr_output,))
testThrd.start()
# in some other process/thread
cmd_line = cmd_output.readline()
thr_line = thr_output.readline()
That's quite difficult. Both your threads are sharing the same stdout. So the output from each of those threads are concurrently sent to your stdout buffer where they are printed in some arbitrary order.
What you need to do is coordinate the output from both threads, and that's a tough nut to crack. Even bash doesn't do that!
That said, maybe you can try using a lock to make sure your threads access stdout in a controlled manner. Check out: http://effbot.org/zone/thread-synchronization.htm
import multiprocessing as mp
import time
"""
1. send item via pipe
2. Receive on the other end by a generator
3. if the pipe is closed on the sending side, retrieve
all item left and then quit.
"""
def foo(conn):
for i in range(7):
time.sleep(.3)
conn.send(i)
conn.close()
def bar(conn):
while True:
try:
yield conn.recv()
except EOFError:
break
if __name__ == '__main__':
"""Choose which start method is used"""
recv_conn, send_conn = mp.Pipe(False)
p = mp.Process(target = foo, args = (send_conn,)) # f can only send msg.
p.start()
# send_conn.close()
for i in bar(recv_conn):
print(i)
I'm using Python 3.4.1 on Ubuntu 14.04 and the code is not working. At the end of the program, there is no EOFError, which should terminates the code, although the Pipe has been closed. Closing the Pipe inside a function does not close the Pipe. Why is this the case?
Uncomment your send_conn.close() line. You should be closing pipe ends in processes that don't need them. The issue is that once you launch the subprocess, the kernel is tracking two open references to the send connection of the pipe: one in the parent process, one in your subprocess.
The send connection object is only being closed in your subprocess, leaving it open in the parent process, so your conn.recv() call won't raise EOFError. The pipe is still open.
This answer may be useful to you as well.
I verified that this code works in Python 2.7.6 if you uncomment the send_conn.close() call.