Windows服务中带有线程和队列的Python open()失败

时间:2019-03-12 19:16:44

标签: python windows multithreading service queue

当我在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)

0 个答案:

没有答案