source: publico/il.spdo/trunk/Paste-1.7.5.1-py2.6.egg/paste/reloader.py @ 5327

Última Alteração nesse arquivo desde 5327 foi 5327, incluída por fabianosantos, 8 anos atrás

Import inicial.

File size: 5.9 KB
Linha 
1# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
2# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
3"""
4A file monitor and server restarter.
5
6Use this like:
7
8..code-block:: Python
9
10    import reloader
11    reloader.install()
12
13Then make sure your server is installed with a shell script like::
14
15    err=3
16    while test "$err" -eq 3 ; do
17        python server.py
18        err="$?"
19    done
20
21or is run from this .bat file (if you use Windows)::
22
23    @echo off
24    :repeat
25        python server.py
26    if %errorlevel% == 3 goto repeat
27
28or run a monitoring process in Python (``paster serve --reload`` does
29this). 
30
31Use the ``watch_file(filename)`` function to cause a reload/restart for
32other other non-Python files (e.g., configuration files).  If you have
33a dynamic set of files that grows over time you can use something like::
34
35    def watch_config_files():
36        return CONFIG_FILE_CACHE.keys()
37    paste.reloader.add_file_callback(watch_config_files)
38
39Then every time the reloader polls files it will call
40``watch_config_files`` and check all the filenames it returns.
41"""
42
43import os
44import sys
45import time
46import threading
47import traceback
48from paste.util.classinstance import classinstancemethod
49
50def install(poll_interval=1):
51    """
52    Install the reloading monitor.
53
54    On some platforms server threads may not terminate when the main
55    thread does, causing ports to remain open/locked.  The
56    ``raise_keyboard_interrupt`` option creates a unignorable signal
57    which causes the whole application to shut-down (rudely).
58    """
59    mon = Monitor(poll_interval=poll_interval)
60    t = threading.Thread(target=mon.periodic_reload)
61    t.setDaemon(True)
62    t.start()
63
64class Monitor(object):
65
66    instances = []
67    global_extra_files = []
68    global_file_callbacks = []
69
70    def __init__(self, poll_interval):
71        self.module_mtimes = {}
72        self.keep_running = True
73        self.poll_interval = poll_interval
74        self.extra_files = list(self.global_extra_files)
75        self.instances.append(self)
76        self.file_callbacks = list(self.global_file_callbacks)
77
78    def periodic_reload(self):
79        while True:
80            if not self.check_reload():
81                # use os._exit() here and not sys.exit() since within a
82                # thread sys.exit() just closes the given thread and
83                # won't kill the process; note os._exit does not call
84                # any atexit callbacks, nor does it do finally blocks,
85                # flush open files, etc.  In otherwords, it is rude.
86                os._exit(3)
87                break
88            time.sleep(self.poll_interval)
89
90    def check_reload(self):
91        filenames = list(self.extra_files)
92        for file_callback in self.file_callbacks:
93            try:
94                filenames.extend(file_callback())
95            except:
96                print >> sys.stderr, "Error calling paste.reloader callback %r:" % file_callback
97                traceback.print_exc()
98        for module in sys.modules.values():
99            try:
100                filename = module.__file__
101            except (AttributeError, ImportError), exc:
102                continue
103            if filename is not None:
104                filenames.append(filename)
105        for filename in filenames:
106            try:
107                stat = os.stat(filename)
108                if stat:
109                    mtime = stat.st_mtime
110                else:
111                    mtime = 0
112            except (OSError, IOError):
113                continue
114            if filename.endswith('.pyc') and os.path.exists(filename[:-1]):
115                mtime = max(os.stat(filename[:-1]).st_mtime, mtime)
116            elif filename.endswith('$py.class') and \
117                    os.path.exists(filename[:-9] + '.py'):
118                mtime = max(os.stat(filename[:-9] + '.py').st_mtime, mtime)
119            if not self.module_mtimes.has_key(filename):
120                self.module_mtimes[filename] = mtime
121            elif self.module_mtimes[filename] < mtime:
122                print >> sys.stderr, (
123                    "%s changed; reloading..." % filename)
124                return False
125        return True
126
127    def watch_file(self, cls, filename):
128        """Watch the named file for changes"""
129        filename = os.path.abspath(filename)
130        if self is None:
131            for instance in cls.instances:
132                instance.watch_file(filename)
133            cls.global_extra_files.append(filename)
134        else:
135            self.extra_files.append(filename)
136
137    watch_file = classinstancemethod(watch_file)
138
139    def add_file_callback(self, cls, callback):
140        """Add a callback -- a function that takes no parameters -- that will
141        return a list of filenames to watch for changes."""
142        if self is None:
143            for instance in cls.instances:
144                instance.add_file_callback(callback)
145            cls.global_file_callbacks.append(callback)
146        else:
147            self.file_callbacks.append(callback)
148
149    add_file_callback = classinstancemethod(add_file_callback)
150
151if sys.platform.startswith('java'):
152    try:
153        from _systemrestart import SystemRestart
154    except ImportError:
155        pass
156    else:
157        class JythonMonitor(Monitor):
158
159            """
160            Monitor that utilizes Jython's special
161            ``_systemrestart.SystemRestart`` exception.
162
163            When raised from the main thread it causes Jython to reload
164            the interpreter in the existing Java process (avoiding
165            startup time).
166
167            Note that this functionality of Jython is experimental and
168            may change in the future.
169            """
170
171            def periodic_reload(self):
172                while True:
173                    if not self.check_reload():
174                        raise SystemRestart()
175                    time.sleep(self.poll_interval)
176
177watch_file = Monitor.watch_file
178add_file_callback = Monitor.add_file_callback
Note: Veja TracBrowser para ajuda no uso do navegador do trac.
 

The contents and data of this website are published under license:
Creative Commons 4.0 Brasil - Atribuir Fonte - Compartilhar Igual.