当我在python中运行它时,我有一个运行良好的程序。问题是,我需要它能够在Windows 10计算机上作为Windows服务运行。
我有几个为其他程序运行的服务,但这是唯一在线程队列中专门使用python的open(filename,'r')方法的服务,并且似乎每次在一个服务中运行该服务都会死掉
当我只是在服务外部运行open(filename,'r')时,Thread and Queue系统非常适合open(filename,'r')。但是,当我在服务中运行此命令时,open(filename,'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)