У меня есть программа, которая прекрасно работает, когда я просто запускаю ее на python. Суть в том, что мне нужно, чтобы он работал в качестве службы Windows на компьютере с Windows 10.
У меня есть несколько сервисов, запущенных для других программ, но это единственный, который специально использует метод python open (filename, 'r') в поточной очереди, и кажется, что при запуске этого в сервисе он умирает каждый раз .
Система Thread и Queue прекрасно работает с open (filename, 'r'), когда я просто запускаю это вне службы. Но когда я запускаю это в сервисе, open (имя файла, 'r') зависает, и код перестает работать. Он не возвращает ошибок, он просто зависает.
У кого-нибудь есть идеи по открытию файла в очереди, запущенного в потоке в службе Windows?
"""
Rough example put together for Stack Overflow.
Original code not sharable.
"""
import os
import win32file
import win32con
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import time
import yaml
import queue
import threading
path_to_watch = "C:/Area51"
# Windows Triggers
ACTIONS = {
1: "Created",
2: "Deleted",
3: "Updated",
4: "Renamed from something",
5: "Renamed to something"
}
# Thanks to Claudio Grondi for the correct set of numbers
FILE_LIST_DIRECTORY = 0x0001
hDir = win32file.CreateFile(
path_to_watch,
FILE_LIST_DIRECTORY,
win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
None,
win32con.OPEN_EXISTING,
win32con.FILE_FLAG_BACKUP_SEMANTICS,
None
)
relative_config_path = '/config/core'
q = queue.Queue()
def process_file(filename=None, template=None, roots=None, proj_id=None, proj_name=None)
# Do something with the data passed to it.
pass
# ---------------------------------------------------------------------------------------------------------------------
# Run Queue
# ---------------------------------------------------------------------------------------------------------------------
def file_queue():
print 'Queue running...'
while True:
package = q.get()
full_filename = package['filename']
template = package['template']
roots = package['roots']
proj_id = package['proj_id']
proj_name = package['proj_name']
copying = True
size2 = -1
while copying:
size = os.stat(full_filename).st_size
if size == size2:
time.sleep(2)
process_file(filename=full_filename, template=template, roots=roots, proj_id=proj_id,
proj_name=proj_name)
copying = False
else:
size2 = os.stat(full_filename).st_size
time.sleep(2)
# Start the thread
t = threading.Thread(target=file_queue, name='FileQueue')
t.setDaemon(True)
t.start()
class remoteAutoPublisher(win32serviceutil.ServiceFramework):
_svc_name_ = "RemoteAutoPublisher"
_svc_display_name_ = "Remote Auto Publisher"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(60)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
self.main()
def main(self):
while 1:
results = win32file.ReadDirectoryChangesW(
hDir,
1024,
True,
win32con.FILE_NOTIFY_CHANGE_FILE_NAME |
win32con.FILE_NOTIFY_CHANGE_DIR_NAME |
win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES |
win32con.FILE_NOTIFY_CHANGE_SIZE |
win32con.FILE_NOTIFY_CHANGE_LAST_WRITE |
win32con.FILE_NOTIFY_CHANGE_SECURITY,
None,
None
)
for action, file in results:
full_filename = os.path.join(path_to_watch, file)
print full_filename, ACTIONS.get(action, "Unknown")
if action == 1:
if os.path.isfile(full_filename):
path = os.path.dirname(full_filename)
rel_path = path.split(path_to_watch)[1]
project_details = get_details_from_path(rel_path) # External: returns dict
proj_name = project_details['name']
proj_id = project_details['id']
if proj_id:
find_config = get_configuration(proj_id) # External: returns a root path from web app
if find_config:
templates_path = find_config + relative_config_path
template_file = os.path.join(templates_path, 'templates.yml')
root_file = os.path.join(templates_path, 'roots.yml')
template_file = template_file.replace('/', '\\')
root_file = root_file.replace('/', '\\')
try:
f = open(template_file, 'r') # This is what is failing in WINDOWS SERVICE
r = open(root_file, 'r') # This is what is failing in WINDOWS SERVICE
except Exception, e:
logger.error('Opening files took a shit.')
template = yaml.load(f)
roots = yaml.load(r)
# Package data into a dict for passing to the queue
package = {'filename': full_filename, 'template': template, 'roots': roots,
'proj_id': proj_id, 'proj_name': proj_name}
q.put(package)
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(remoteAutoPublisher)