Delay load calibre C extensions. Worker launch is now under 0.07 seconds (only about 3 times the time taken to launch bare python)

This commit is contained in:
Kovid Goyal 2011-04-20 14:06:56 -06:00
parent 303a7c6b5c
commit 7fc7478c97
3 changed files with 48 additions and 24 deletions

View File

@ -12,7 +12,7 @@ __author__ = u"Kovid Goyal <kovid@kovidgoyal.net>"
Various run time constants. Various run time constants.
''' '''
import sys, locale, codecs, os, importlib import sys, locale, codecs, os, importlib, collections
_tc = None _tc = None
def terminal_controller(): def terminal_controller():
@ -52,15 +52,12 @@ def debug():
DEBUG = True DEBUG = True
# plugins {{{ # plugins {{{
plugins = None
if plugins is None:
# Load plugins
def load_plugins():
plugins = {}
plugin_path = sys.extensions_location
sys.path.insert(0, plugin_path)
for plugin in [ class Plugins(collections.Mapping):
def __init__(self):
self._plugins = {}
plugins = [
'pictureflow', 'pictureflow',
'lzx', 'lzx',
'msdes', 'msdes',
@ -74,19 +71,44 @@ if plugins is None:
'chm_extra', 'chm_extra',
'icu', 'icu',
'speedup', 'speedup',
] + \ ]
(['winutil'] if iswindows else []) + \ if iswindows:
(['usbobserver'] if isosx else []): plugins.append('winutil')
try: if isosx:
p, err = importlib.import_module(plugin), '' plugins.append(['usbobserver'])
except Exception as err: self.plugins = frozenset(plugins)
p = None
err = str(err)
plugins[plugin] = (p, err)
sys.path.remove(plugin_path)
return plugins
plugins = load_plugins() def load_plugin(self, name):
if name in self._plugins:
return
sys.path.insert(0, sys.extensions_location)
try:
p, err = importlib.import_module(name), ''
except Exception as err:
p = None
err = str(err)
self._plugins[name] = (p, err)
sys.path.remove(sys.extensions_location)
def __iter__(self):
return iter(self.plugins)
def __len__(self):
return len(self.plugins)
def __contains__(self, name):
return name in self.plugins
def __getitem__(self, name):
if name not in self.plugins:
raise KeyError('No plugin named %r'%name)
self.load_plugin(name)
return self._plugins[name]
plugins = None
if plugins is None:
plugins = Plugins()
# }}} # }}}
# config_dir {{{ # config_dir {{{

View File

@ -8,7 +8,7 @@ manner.
import sys, os, re import sys, os, re
from threading import RLock from threading import RLock
from calibre import iswindows, isosx, plugins, islinux from calibre.constants import iswindows, isosx, plugins, islinux
osx_scanner = win_scanner = linux_scanner = None osx_scanner = win_scanner = linux_scanner = None

View File

@ -19,6 +19,9 @@ from calibre.utils.config import prefs, dynamic
from calibre.library.database2 import LibraryDatabase2 from calibre.library.database2 import LibraryDatabase2
from calibre.library.sqlite import sqlite, DatabaseException from calibre.library.sqlite import sqlite, DatabaseException
if iswindows:
winutil = plugins['winutil'][0]
def option_parser(): def option_parser():
parser = _option_parser('''\ parser = _option_parser('''\
%prog [opts] [path_to_ebook] %prog [opts] [path_to_ebook]
@ -80,8 +83,7 @@ def get_library_path(parent=None):
if library_path is None: # Need to migrate to new database layout if library_path is None: # Need to migrate to new database layout
base = os.path.expanduser('~') base = os.path.expanduser('~')
if iswindows: if iswindows:
base = plugins['winutil'][0].special_folder_path( base = winutil.special_folder_path(winutil.CSIDL_PERSONAL)
plugins['winutil'][0].CSIDL_PERSONAL)
if not base or not os.path.exists(base): if not base or not os.path.exists(base):
from PyQt4.Qt import QDir from PyQt4.Qt import QDir
base = unicode(QDir.homePath()).replace('/', os.sep) base = unicode(QDir.homePath()).replace('/', os.sep)