Python open () не работает в Windows Service с потоком и очередью - PullRequest
0 голосов
/ 12 марта 2019

У меня есть программа, которая прекрасно работает, когда я просто запускаю ее на 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...