Mutex Destroy Failing on RP4 Port - python

Wed Mar 16, 2022 9:43 pm
Hi, I am relatively new to the Raspberry Pi and have been trying to port some Python source code originally compiled for Windows to a Pi 4. I was able to port everything over save for Win32API, I ended up commenting out "import win32api".
The python code runs until the last error handling statement and I believe it has to do with win32api. Whenever I run this code, I get the error "python3:../../libusb/os/threads_posix.h:58: usbi_mutex_destroy: Assertion `pthread_mutex_destroy(mutex) == 0' failed."
The bit of code that I've traced it to is:
if __name__ == '__main__':
# vp_start_gui()
# find_usb_port()
root = tk.Tk()
prog_call = sys.argv[0]
prog_location = os.path.split(prog_call)[0]
define.APP_LOCATION = prog_location
file_location = os.path.join(prog_location, "./project_loc.txt")
# Get project folder path
f = open(file_location, 'r')
file_loc = f.read().replace('\n', '').strip()
f.close()
define.ASSAY_FOLDER_PATH = str(file_loc)
# print("define.ASSAY_FOLDER_PATH11: ", define.ASSAY_FOLDER_PATH)
try:
while define.ASSAY_FOLDER_PATH == "":
define.LOAD_ASSAY_FILE = True
resp = tkinter.messagebox.askokcancel('Select Directory for Assay files: ',
"Select a directory for Assay files and log files")
if resp is True:
define.ASSAY_FOLDER_PATH = filedialog.askdirectory(title='Select a directory for INT05 Project')
else:
root.destroy()
sys.exit()
# Save the log folder file to log_loc.txt to save logs
f = open(file_location, 'w')
f.writelines(str(define.ASSAY_FOLDER_PATH))
f.close()
# debug_print("define.ASSAY_FOLDER_PATH: ", define.ASSAY_FOLDER_PATH)
client = ThreadedClient(root)
root.mainloop()
except Exception as e:
# debug_print(e)
messagebox.showerror("ERROR", "Run the app with administrative privilege... "
"(This has to be done on very first run!")
sys.exit()
When run, the GUI pops up with the "ERROR", "Run the app with administrative privilege..." statement regardless if I run the code as root.
Any ideas on what I am doing wrong or how to get around this error would be greatly appreciated! I've been spinning my wheels on this for awhile now.
Thanks!

Related

How to quit script when Telebot sees a new message

I have two python scripts which I run using a batch script. Once one script is executed, the next script starts. I need one of the scripts, the Telebot script, to quit after recording a message in a .json file. Unfortunately, while the message does get recorded, I am having trouble quitting the script, meaning my second python file is not being executed.
import telebot
import json
import os
import sys
import time
with open('JSON_file.json') as f:
data = json.load(f)
group_chat_id = 'CHAT_ID_HERE'
hbot = telebot.TeleBot('BOT_TOKEN_HERE')
hbot.send_photo(chat_id = group_chat_id, caption = data, photo = open('C:/Users/.../image.jpg', 'rb'))
temp = ""
#hbot.message_handler(func=lambda message: True)
def get_input(message):
global temp
message_str = str(message.text)
message_str = message_str.strip()
temp = message_str
print(temp)
with open('JSON_file.json', 'w') as json_file:
json.dump(temp, json_file)
hbot.stop_polling()
if temp != "":
quit()
return
if __name__ == "__main__":
hbot.polling()
I run the code(s) using an executable .bat file, however, the code below does not quit once a message is received. Does anyone know why the quit() command does not stop my code?
Thanks in advance)
I'd recommend using sys.exit instead of quit: https://docs.python.org/3/library/sys.html#sys.exit
In python, we have an in-built quit() function which is used to exit a python program. When it encounters the quit() function in the system, it terminates the execution of the program completely.
It should not be used in production code and this function should only be used in the interpreter.
Source: https://pythonguides.com/python-exit-command/

Python script completes when run as user but not when run as root

I'm new to Linux and am struggling a bit with a script
Hardware: Raspberry Pi Zero W
OS: Raspberry Pi OS Lite
the main script listen.py is waiting for a button push or udp command an then triggers the function take_image_ftp():
def take_image_ftp():
global scancounter
global isTakingImage
global denominator
global counter
global BUTTON
if isTakingImage == False:
isTakingImage = True
GPIO.remove_event_detect(BUTTON)
shutter = 1000000 / denominator #in microseconds
timea = datetime.utcnow()
print("taking image...")
subprocess.call(['raspistill -o /home/pi/startup/current.jpg --raw -md 3 -awb flash -q 100 -ex spotlight --timeout 2 --nopreview --shutter ' + str(shutter) +' --ISO 100'], shell=True)
time.sleep(1)
print("extracting dng...")
subprocess.check_call(['python3.7 /home/pi/PyDNG/examples/utility.py current.jpg'], shell=True)
timeb = datetime.utcnow()
print("uploading image")
from ftplib import FTP
ftp = FTP(host="192.168.178.34",user='**', passwd='**')
ftp.set_pasv(True)
ftp.debug(0)
counter += 1
# print("Shutter : " + str(shutter))
#print ("logging in to ftp server ")
try:
ftp.login("Medusa", "Medusa")
except ftplib.all_errors as e:
# print('FTP error:', e)
sys.exc_clear()
# print("creating directory")
try:
ftp.cwd("images/")
except ftplib.all_errors as e:
# print('FTP error:', e)
sys.exc_clear()
foldername = "img" + str(counter)
if foldername not in ftp.nlst():
# print("folder does not exist. creating")
try:
ftp.mkd(foldername)
except ftplib.all_errors as e:
# print('FTP error:', e)
sys.exc_clear()
try:
ftp.cwd(foldername)
except ftplib.all_errors as e:
#print('FTP error:', e)
sys.exc_clear()
if os.path.isfile('/home/pi/startup/current.dng'):
file = open("/home/pi/startup/current.dng", "rb")
else:
file = open("/home/pi/startup/listen.py","rb")
ftp.storbinary("STOR " + str(get_ip_address('wlan0')) + ".dng", file)
file.close()
ftp.quit()
timer = threading.Timer(5, resetCounter)
timer.start()
#print("\n")
print("---------SCAN SENT--------")
#GPIO.add_event_detect(BUTTON, GPIO.RISING, callback=button_callback, bouncetime=200)
print timeb - timea
It takes an image via raspistill(), then extracts the raw data from the captured image via PyDNG and then uploads the dng file via ftp.
When run via ssh as user pi it works like a charm, but when run via a autostart as root it craps (edit: runs out of memory) out at extracting the raw data. Which leads to the last image converted when run as user pi being uploaded.
helper script:
import socket
import struct
import fcntl
import subprocess
import sys
import ftplib
import time
import threading
import os
from time import sleep
print("updateing scripts")
try:
ftp = ftplib.FTP("192.168.178.34", "**", "**")
ftp.login("**", "**")
lf = open("/home/pi/startup/listen.py", "wb")
ftp.retrbinary("RETR " + "listen.py", lf.write, 8*1024)
lf.close()
lf = open("/home/pi/startup/focus.py", "wb")
ftp.retrbinary("RETR " + "focus.py", lf.write, 8*1024)
lf.close()
ftp.quit()
except ftplib.all_errors as e:
print('FTP error:', e)
print("done")
print ("starting listen script")
cmd = ("python /home/pi/startup/listen.py")
subprocess.call(cmd, shell=True)
The helper script starts via /etc/rc.local sudo python /home/pi/startup/start.py &
If any of you could point me in the right direction, I'd very much appreciate it.
Oh, boy...
Here is the actual problem:
When ssh-ing into the pi I change the working directory to the folder /startup.
When running the script from systemd ... I didn't.
convert ('/home/pi/startup/current.jpg') instead of convert ('current.jpg')
goddamn hours man, goddamn hours.
Edit: the raspi did actually run out of memory when extracting the raw info from raspistill to dng using subprocess.call - so all the trouble was worth the effort!
thanks to everybody that replied!

You do not have permission to open this file' when using os.system() [duplicate]

I am writing a pyqt application which require to execute admin task. I would prefer to start my script with elevate privilege. I am aware that this question is asked many times in SO or in other forum. But the solution people are suggesting is to have a look at this SO question
Request UAC elevation from within a Python script?
However, I am unable to execute the sample code given in the link. I have put this code on top of the main file and tried to execute it.
import os
import sys
import win32com.shell.shell as shell
ASADMIN = 'asadmin'
if sys.argv[-1] != ASADMIN:
script = os.path.abspath(sys.argv[0])
params = ' '.join([script] + sys.argv[1:] + [ASADMIN])
shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params)
sys.exit(0)
print "I am root now."
It actually ask permission to elevate but print line never get executed. Somebody can help me to run the above code successfully.
Update as on 19-02-2023
The update to the below script is now alive as a Python package by the same author. You can install it from PyPi which lives at https://pypi.org/project/pyuac/ and the source code/ home page is located at https://github.com/Preston-Landers/pyuac. Install it using:
pip install pyuac
Direct usage of the package is:
import pyuac
def main():
print("Do stuff here that requires being run as an admin.")
# The window will disappear as soon as the program exits!
input("Press enter to close the window. >")
if __name__ == "__main__":
if not pyuac.isUserAdmin():
print("Re-launching as admin!")
pyuac.runAsAdmin()
else:
main() # Already an admin here.
or if you wish to use it using decorater:
from pyuac import main_requires_admin
#main_requires_admin
def main():
print("Do stuff here that requires being run as an admin.")
# The window will disappear as soon as the program exits!
input("Press enter to close the window. >")
if __name__ == "__main__":
main()
Original answer
Thank you all for your reply. I got my script working with the module/ script written by Preston Landers in 2010. After two days of browsing the internet, I could find the script as it was deeply hidden in the pywin32 mailing list. With this script, it is easier to check if the user is admin, and if not then ask for UAC/ admin right. It does provide output in separate windows to find out what the code is doing. An example of how to use the code is also included in the script. For the benefit of all who are looking for UAC on windows have a look at this code. I hope it helps someone looking for the same solution. It can be used something like this from your main script:-
import admin
if not admin.isUserAdmin():
admin.runAsAdmin()
The actual code is:-
#!/usr/bin/env python
# -*- coding: utf-8; mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vim: fileencoding=utf-8 tabstop=4 expandtab shiftwidth=4
# (C) COPYRIGHT © Preston Landers 2010
# Released under the same license as Python 2.6.5
import sys, os, traceback, types
def isUserAdmin():
if os.name == 'nt':
import ctypes
# WARNING: requires Windows XP SP2 or higher!
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
traceback.print_exc()
print "Admin check failed, assuming not an admin."
return False
elif os.name == 'posix':
# Check for root on Posix
return os.getuid() == 0
else:
raise RuntimeError, "Unsupported operating system for this module: %s" % (os.name,)
def runAsAdmin(cmdLine=None, wait=True):
if os.name != 'nt':
raise RuntimeError, "This function is only implemented on Windows."
import win32api, win32con, win32event, win32process
from win32com.shell.shell import ShellExecuteEx
from win32com.shell import shellcon
python_exe = sys.executable
if cmdLine is None:
cmdLine = [python_exe] + sys.argv
elif type(cmdLine) not in (types.TupleType,types.ListType):
raise ValueError, "cmdLine is not a sequence."
cmd = '"%s"' % (cmdLine[0],)
# XXX TODO: isn't there a function or something we can call to massage command line params?
params = " ".join(['"%s"' % (x,) for x in cmdLine[1:]])
cmdDir = ''
showCmd = win32con.SW_SHOWNORMAL
#showCmd = win32con.SW_HIDE
lpVerb = 'runas' # causes UAC elevation prompt.
# print "Running", cmd, params
# ShellExecute() doesn't seem to allow us to fetch the PID or handle
# of the process, so we can't get anything useful from it. Therefore
# the more complex ShellExecuteEx() must be used.
# procHandle = win32api.ShellExecute(0, lpVerb, cmd, params, cmdDir, showCmd)
procInfo = ShellExecuteEx(nShow=showCmd,
fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
lpVerb=lpVerb,
lpFile=cmd,
lpParameters=params)
if wait:
procHandle = procInfo['hProcess']
obj = win32event.WaitForSingleObject(procHandle, win32event.INFINITE)
rc = win32process.GetExitCodeProcess(procHandle)
#print "Process handle %s returned code %s" % (procHandle, rc)
else:
rc = None
return rc
def test():
rc = 0
if not isUserAdmin():
print "You're not an admin.", os.getpid(), "params: ", sys.argv
#rc = runAsAdmin(["c:\\Windows\\notepad.exe"])
rc = runAsAdmin()
else:
print "You are an admin!", os.getpid(), "params: ", sys.argv
rc = 0
x = raw_input('Press Enter to exit.')
return rc
if __name__ == "__main__":
sys.exit(test())
in comments to the answer you took the code from someone says ShellExecuteEx doesn't post its STDOUT back to the originating shell. so you will not see "I am root now", even though the code is probably working fine.
instead of printing something, try writing to a file:
import os
import sys
import win32com.shell.shell as shell
ASADMIN = 'asadmin'
if sys.argv[-1] != ASADMIN:
script = os.path.abspath(sys.argv[0])
params = ' '.join([script] + sys.argv[1:] + [ASADMIN])
shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params)
sys.exit(0)
with open("somefilename.txt", "w") as out:
print >> out, "i am root"
and then look in the file.
I found a very easy solution to this problem.
Create a shortcut for python.exe
Change the shortcut target into something like C:\xxx\...\python.exe your_script.py
Click "advance..." in the property panel of the shortcut, and click the option "run as administrator"
I'm not sure whether the spells of these options are right, since I'm using Chinese version of Windows.
Here is a solution which needed ctypes module only. Support pyinstaller wrapped program.
#!python
# coding: utf-8
import sys
import ctypes
def run_as_admin(argv=None, debug=False):
shell32 = ctypes.windll.shell32
if argv is None and shell32.IsUserAnAdmin():
return True
if argv is None:
argv = sys.argv
if hasattr(sys, '_MEIPASS'):
# Support pyinstaller wrapped program.
arguments = map(unicode, argv[1:])
else:
arguments = map(unicode, argv)
argument_line = u' '.join(arguments)
executable = unicode(sys.executable)
if debug:
print 'Command line: ', executable, argument_line
ret = shell32.ShellExecuteW(None, u"runas", executable, argument_line, None, 1)
if int(ret) <= 32:
return False
return None
if __name__ == '__main__':
ret = run_as_admin()
if ret is True:
print 'I have admin privilege.'
raw_input('Press ENTER to exit.')
elif ret is None:
print 'I am elevating to admin privilege.'
raw_input('Press ENTER to exit.')
else:
print 'Error(ret=%d): cannot elevate privilege.' % (ret, )
Here is a solution with an stdout redirection:
def elevate():
import ctypes, win32com.shell.shell, win32event, win32process
outpath = r'%s\%s.out' % (os.environ["TEMP"], os.path.basename(__file__))
if ctypes.windll.shell32.IsUserAnAdmin():
if os.path.isfile(outpath):
sys.stderr = sys.stdout = open(outpath, 'w', 0)
return
with open(outpath, 'w+', 0) as outfile:
hProc = win32com.shell.shell.ShellExecuteEx(lpFile=sys.executable, \
lpVerb='runas', lpParameters=' '.join(sys.argv), fMask=64, nShow=0)['hProcess']
while True:
hr = win32event.WaitForSingleObject(hProc, 40)
while True:
line = outfile.readline()
if not line: break
sys.stdout.write(line)
if hr != 0x102: break
os.remove(outpath)
sys.stderr = ''
sys.exit(win32process.GetExitCodeProcess(hProc))
if __name__ == '__main__':
elevate()
main()
It worth mentioning that if you intend to package your application with PyInstaller and wish to avoid supporting that feature by yourself, you can pass the --uac-admin or --uac-uiaccess argument in order to request UAC elevation on start.
make a batch file
add python.exe "(your py file here)" with the quotation marks
save the batch file
right click, then click run as administrator
Also if your working directory is different than you can use lpDirectory
procInfo = ShellExecuteEx(nShow=showCmd,
lpVerb=lpVerb,
lpFile=cmd,
lpDirectory= unicode(direc),
lpParameters=params)
Will come handy if changing the path is not a desirable option
remove unicode for python 3.X
This worked for me:
import win32com.client as client
required_command = "cmd" # Enter your command here
required_password = "Simple1" # Enter your password here
def run_as(required_command, required_password):
shell = client.Dispatch("WScript.shell")
shell.Run(f"runas /user:administrator {required_command}")
time.sleep(1)
shell.SendKeys(f"{required_password}\r\n", 0)
if __name__ = '__main__':
run_as(required_command, required_password)
Below are the references I used for above code:
https://win32com.goermezer.de/microsoft/windows/controlling-applications-via-sendkeys.html
https://www.oreilly.com/library/view/python-cookbook/0596001673/ch07s16.html
Use pyuac
it is the update to the orignal admin Script by Preston Landers
Link to python Projects: https://pypi.org/project/pyuac/
Github: https://github.com/Preston-Landers/pyuac
This worked for me it
from pyuac import main_requires_admin
#main_requires_admin
def main():
print("Do stuff here that requires being run as an admin.")
# The window will disappear as soon as the program exits!
input("Press enter to close the window. >")
if __name__ == "__main__":
main()
JetBrains' WinElevator (signed elevator.exe and launcher.exe available here) allows you to spawn a subprocess that requests elevated privileges while keeping stdin/stdout/stderr intact:
import ctypes
import subprocess
import sys
if not ctypes.windll.shell32.IsUserAnAdmin():
print("not an admin, restarting...")
subprocess.run(["launcher.exe", sys.executable, *sys.argv])
else:
print("I'm an admin now.")
> python example.py
not an admin, restarting...
# UAC prompt is shown
I'm an admin now.
I can confirm that the solution by delphifirst works and is the easiest, simplest solution to the problem of running a python script with elevated privileges.
I created a shortcut to the python executable (python.exe) and then modified the shortcut by adding my script's name after the call to python.exe. Next I checked "run as administrator" on the "compatibility tab" of the shortcut. When the shortcut is executed, you get a prompt asking permission to run the script as an administrator.
My particular python application was an installer program. The program allows installing and uninstalling another python app. In my case I created two shortcuts, one named "appname install" and the other named "appname uninstall". The only difference between the two shortcuts is the argument following the python script name. In the installer version the argument is "install". In the uninstall version the argument is "uninstall". Code in the installer script evaluates the argument supplied and calls the appropriate function (install or uninstall) as needed.
I hope my explanation helps others more quickly figure out how to run a python script with elevated privileges.
Make sure you have python in path,if not,win key + r, type in "%appdata%"(without the qotes) open local directory, then go to Programs directory ,open python and then select your python version directory. Click on file tab and select copy path and close file explorer.
Then do win key + r again, type control and hit enter. search for environment variables. click on the result, you will get a window. In the bottom right corner click on environmental variables. In the system side find path, select it and click on edit.
In the new window, click on new and paste the path in there. Click ok and then apply in the first window. Restart your PC. Then do win + r for the last time, type cmd and do ctrl + shift + enter. Grant the previliges and open file explorer, goto your script and copy its path. Go back into cmd , type in "python" and paste the path and hit enter. Done
I wanted a more enhanced version so I ended up with a module which allows:
UAC request if needed, printing and logging from nonprivileged instance (uses ipc and a network port) and some other candies. usage is just insert elevateme() in your script: in nonprivileged it listen for privileged print/logs and then exits returning false, in privileged instance it returns true immediately.
Supports pyinstaller.
prototype:
# xlogger : a logger in the server/nonprivileged script
# tport : open port of communication, 0 for no comm [printf in nonprivileged window or silent]
# redir : redirect stdout and stderr from privileged instance
#errFile : redirect stderr to file from privileged instance
def elevateme(xlogger=None, tport=6000, redir=True, errFile=False):
winadmin.py
#!/usr/bin/env python
# -*- coding: utf-8; mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vim: fileencoding=utf-8 tabstop=4 expandtab shiftwidth=4
# (C) COPYRIGHT © Preston Landers 2010
# (C) COPYRIGHT © Matteo Azzali 2020
# Released under the same license as Python 2.6.5/3.7
import sys, os
from traceback import print_exc
from multiprocessing.connection import Listener, Client
import win32event #win32com.shell.shell, win32process
import builtins as __builtin__ # python3
# debug suffixes for remote printing
dbz=["","","",""] #["J:","K:", "G:", "D:"]
LOGTAG="LOGME:"
wrconn = None
#fake logger for message sending
class fakelogger:
def __init__(self, xlogger=None):
self.lg = xlogger
def write(self, a):
global wrconn
if wrconn is not None:
wrconn.send(LOGTAG+a)
elif self.lg is not None:
self.lg.write(a)
else:
print(LOGTAG+a)
class Writer():
wzconn=None
counter = 0
def __init__(self, tport=6000,authkey=b'secret password'):
global wrconn
if wrconn is None:
address = ('localhost', tport)
try:
wrconn = Client(address, authkey=authkey)
except:
wrconn = None
wzconn = wrconn
self.wrconn = wrconn
self.__class__.counter+=1
def __del__(self):
self.__class__.counter-=1
if self.__class__.counter == 0 and wrconn is not None:
import time
time.sleep(0.1) # slows deletion but is enough to print stderr
wrconn.send('close')
wrconn.close()
def sendx(cls, mesg):
cls.wzconn.send(msg)
def sendw(self, mesg):
self.wrconn.send(msg)
#fake file to be passed as stdout and stderr
class connFile():
def __init__(self, thekind="out", tport=6000):
self.cnt = 0
self.old=""
self.vg=Writer(tport)
if thekind == "out":
self.kind=sys.__stdout__
else:
self.kind=sys.__stderr__
def write(self, *args, **kwargs):
global wrconn
global dbz
from io import StringIO # # Python2 use: from cStringIO import StringIO
mystdout = StringIO()
self.cnt+=1
__builtin__.print(*args, **kwargs, file=mystdout, end = '')
#handles "\n" wherever it is, however usually is or string or \n
if "\n" not in mystdout.getvalue():
if mystdout.getvalue() != "\n":
#__builtin__.print("A:",mystdout.getvalue(), file=self.kind, end='')
self.old += mystdout.getvalue()
else:
#__builtin__.print("B:",mystdout.getvalue(), file=self.kind, end='')
if wrconn is not None:
wrconn.send(dbz[1]+self.old)
else:
__builtin__.print(dbz[2]+self.old+ mystdout.getvalue(), file=self.kind, end='')
self.kind.flush()
self.old=""
else:
vv = mystdout.getvalue().split("\n")
#__builtin__.print("V:",vv, file=self.kind, end='')
for el in vv[:-1]:
if wrconn is not None:
wrconn.send(dbz[0]+self.old+el)
self.old = ""
else:
__builtin__.print(dbz[3]+self.old+ el+"\n", file=self.kind, end='')
self.kind.flush()
self.old=""
self.old=vv[-1]
def open(self):
pass
def close(self):
pass
def flush(self):
pass
def isUserAdmin():
if os.name == 'nt':
import ctypes
# WARNING: requires Windows XP SP2 or higher!
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
traceback.print_exc()
print ("Admin check failed, assuming not an admin.")
return False
elif os.name == 'posix':
# Check for root on Posix
return os.getuid() == 0
else:
print("Unsupported operating system for this module: %s" % (os.name,))
exit()
#raise (RuntimeError, "Unsupported operating system for this module: %s" % (os.name,))
def runAsAdmin(cmdLine=None, wait=True, hidden=False):
if os.name != 'nt':
raise (RuntimeError, "This function is only implemented on Windows.")
import win32api, win32con, win32process
from win32com.shell.shell import ShellExecuteEx
python_exe = sys.executable
arb=""
if cmdLine is None:
cmdLine = [python_exe] + sys.argv
elif not isinstance(cmdLine, (tuple, list)):
if isinstance(cmdLine, (str)):
arb=cmdLine
cmdLine = [python_exe] + sys.argv
print("original user", arb)
else:
raise( ValueError, "cmdLine is not a sequence.")
cmd = '"%s"' % (cmdLine[0],)
params = " ".join(['"%s"' % (x,) for x in cmdLine[1:]])
if len(arb) > 0:
params += " "+arb
cmdDir = ''
if hidden:
showCmd = win32con.SW_HIDE
else:
showCmd = win32con.SW_SHOWNORMAL
lpVerb = 'runas' # causes UAC elevation prompt.
# print "Running", cmd, params
# ShellExecute() doesn't seem to allow us to fetch the PID or handle
# of the process, so we can't get anything useful from it. Therefore
# the more complex ShellExecuteEx() must be used.
# procHandle = win32api.ShellExecute(0, lpVerb, cmd, params, cmdDir, showCmd)
procInfo = ShellExecuteEx(nShow=showCmd,
fMask=64,
lpVerb=lpVerb,
lpFile=cmd,
lpParameters=params)
if wait:
procHandle = procInfo['hProcess']
obj = win32event.WaitForSingleObject(procHandle, win32event.INFINITE)
rc = win32process.GetExitCodeProcess(procHandle)
#print "Process handle %s returned code %s" % (procHandle, rc)
else:
rc = procInfo['hProcess']
return rc
# xlogger : a logger in the server/nonprivileged script
# tport : open port of communication, 0 for no comm [printf in nonprivileged window or silent]
# redir : redirect stdout and stderr from privileged instance
#errFile : redirect stderr to file from privileged instance
def elevateme(xlogger=None, tport=6000, redir=True, errFile=False):
global dbz
if not isUserAdmin():
print ("You're not an admin.", os.getpid(), "params: ", sys.argv)
import getpass
uname = getpass.getuser()
if (tport> 0):
address = ('localhost', tport) # family is deduced to be 'AF_INET'
listener = Listener(address, authkey=b'secret password')
rc = runAsAdmin(uname, wait=False, hidden=True)
if (tport> 0):
hr = win32event.WaitForSingleObject(rc, 40)
conn = listener.accept()
print ('connection accepted from', listener.last_accepted)
sys.stdout.flush()
while True:
msg = conn.recv()
# do something with msg
if msg == 'close':
conn.close()
break
else:
if msg.startswith(dbz[0]+LOGTAG):
if xlogger != None:
xlogger.write(msg[len(LOGTAG):])
else:
print("Missing a logger")
else:
print(msg)
sys.stdout.flush()
listener.close()
else: #no port connection, its silent
WaitForSingleObject(rc, INFINITE);
return False
else:
#redirect prints stdout on master, errors in error.txt
print("HIADM")
sys.stdout.flush()
if (tport > 0) and (redir):
vox= connFile(tport=tport)
sys.stdout=vox
if not errFile:
sys.stderr=vox
else:
vfrs=open("errFile.txt","w")
sys.stderr=vfrs
#print("HI ADMIN")
return True
def test():
rc = 0
if not isUserAdmin():
print ("You're not an admin.", os.getpid(), "params: ", sys.argv)
sys.stdout.flush()
#rc = runAsAdmin(["c:\\Windows\\notepad.exe"])
rc = runAsAdmin()
else:
print ("You are an admin!", os.getpid(), "params: ", sys.argv)
rc = 0
x = raw_input('Press Enter to exit.')
return rc
if __name__ == "__main__":
sys.exit(test())

subprocess.Popen will not run my python program

So I tried making a launcher for a text games that I am making and I need the launcher to run a part of the game based on what expansions I picked. However, after creating the launcher and testing it, I realised that everything works fine up until the part where the launcher is supposed to execute another python program. Instead of executing the program, it just ends and I am not sure why. Here is my code:
import easygui as e
import os
import subprocess
def Launch():
expansions = []
file = open("dlc.txt")
reading = True
while reading == True:
temp = file.readline().strip()
if temp == "":
reading = False
elif temp == "The Forgotten Lands":
expansions.append("The Forgotten Lands (Main Game)")
else:
expansions.append(temp)
game = e.choicebox("Welcome to The Forgotten Lands launcher. Please pick an expansion.","Launcher",choices=expansions)
if game is None:
os._exit(0)
else:
if game == "The Forgotten Lands (Main Game)":
game = "The Forgotten Lands"
dir_path = os.path.dirname(os.path.realpath(__file__))
filepath = (dir_path + "/" + game + "/" + game + ".py")
filepath = filepath.replace("/", "\/")
filepath = filepath.replace("/", "")
subprocess.Popen(filepath, shell=True)
Launch()
It should be:
subprocess.Popen("python " + filepath, shell=True)
If that doesn't work, would you be able to put the output of the code please?

python automate ffmpeg conversion from upload directory

I have a upload script done. But i need to figure out how to make a script that I can run as a daemon in python to handle the conversion part and moving the file thats converted to its final resting place. heres what I have so far for the directory watcher script:
#!/usr/bin/python
import os
import pyinotify import WatchManager, Notifier, ThreadedNotifier, ProcessEvent, EventCodes
import sys, time, syslog, config
from os import system
from daemon import Daemon
class myLog(ProcessEvent):
def process_IN_CREATE(self, event):
syslog.syslog("creating: " + event.pathname)
def process_IN_DELETE(self, event):
syslog.syslog("deleting: " + event.pathname)
def process_default(self, event):
syslog.syslog("default: " + event.pathname)
class MyDaemon(Daemon):
def loadConfig(self):
"""Load user configuration file"""
self.config = {}
self.parser = ConfigParser.ConfigParser()
if not os.path.isfile(self.configfile):
self.parser.write(open(self.configfile, 'w'))
self.parser.readfp(open(self.configfile, 'r'))
variables = { \
'mplayer': ['paths', self.findProgram("mplayer")], \
'mencoder': ['paths', self.findProgram("mencoder")], \
'tcprobe': ['paths', self.findProgram("tcprobe")], \
'transcode': ['paths', self.findProgram("transcode")], \
'ogmmerge': ['paths', self.findProgram("ogmmerge")], \
'outputdir': ['paths', os.path.expanduser("~")], \
}
for key in variables.keys():
self.cautiousLoad(variables[key][0], key, variables[key][1])
def cautiousLoad(self, section, var, default):
"""Load a configurable variable within an exception clause,
in case variable is not in configuration file"""
try:
self.config[var] = int(self.parser.get(section, var))
except:
self.config[var] = default
try:
self.parser.set(section, var, default)
except:
self.parser.add_section(section)
self.parser.set(section, var, default)
self.parser.write(open(self.configfile, 'w'))
def findProgram(self, program):
"""Looks for program in path, and returns full path if found"""
for path in config.paths:
if os.path.isfile(os.path.join(path, program)):
return os.path.join(path, program)
self.ui_configError(program)
def run(self):
syslog.openlog('mediaConvertor', syslog.LOG_PID,syslog.LOG_DAEMON)
syslog.syslog('daemon started, entering loop')
wm = WatchManager()
mask = IN_DELETE | IN_CREATE
notifier = ThreadedNotifier(wm, myLog())
notifier.start()
wdd = wm.add_watch(self.config['outputdir'], mask, rec=True)
while True:
time.sleep(1)
wm.rm_watch(wdd.values())
notifier.stop()
syslog.syslog('exiting media convertor')
syslog.closelog()
if __name__ == "__main__":
daemon = MyDaemon('/tmp/mediaconvertor.pid')
if len(sys.argv) == 2:
if 'start' == sys.argv[1]:
daemon.run()
if 'stop' == sys.argv[1]:
daemon.stop()
if 'restart' == sys.argv[1]:
daemon.restart()
else:
print "Unknown Command"
sys.exit(2)
sys.exit(0)
else:
print "Usage: %s start|stop|restart" % sys.argv[0]
sys.exit(2)
not sure where to go from here.
I don't run on Linux and have never used the inotify capabilities you are using here. I'll describe how I would do things generically.
In the simplest case, you need to check if there's a new file in the upload directory and when there is one, start doing the conversion notification.
To check if there are new files you can do something like:
import os
import time
def watch_directory(dirname="."):
old_files = set(os.listdir(dirname))
while 1:
time.sleep(1)
new_files = set(os.listdir(dirname))
diff = new_files - old_files
if diff:
print "New files", diff
old_files = new_files
watch_directory()
You may be able to minimize some filesystem overhead by first stat'ing the directory to see if there are any changes.
def watch_directory(dirname="."):
old_files = set(os.listdir(dirname))
old_stat = os.stat(dirname)
while 1:
time.sleep(1)
new_stat = os.stat(dirname)
if new_stat == old_stat:
continue
new_files = set(os.listdir(dirname))
diff = new_files - old_files
if diff:
print "New files", diff
old_stat = new_stat
old_files = new_files
With inotify I think this is all handled for you, and you put your code into process_IN_CREATE() which gets called when a new file is available.
One bit of trickiness - how does the watcher know that the upload is complete? What happens if the upload is canceled part-way through uploading? This could be as simple as having the web server do a rename() to use one extension during upload and another extension when done.
Once you know the file, use subprocess.Popen(conversion_program, "new_filename") or os.system("conversion_program new_filename &") to spawn off the conversion in a new process which does the conversion. You'll need to handle things like error reporting, as when the input isn't in the right format. It should also clean up, meaning that once the conversion is done it should remove the input file from consideration. This might be as easy as deleting the file.
You'll also need to worry about restarting any conversions which were killed. If the machine does down, how does the restarted watcher know which data file conversions were also killed and need to be restarted. But this might be doable as a manual step.

Categories

Resources