__init__.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. '''
  2. OpenCV Python binary extension loader
  3. '''
  4. import os
  5. import importlib
  6. import sys
  7. __all__ = []
  8. try:
  9. import numpy
  10. import numpy.core.multiarray
  11. except ImportError:
  12. print('OpenCV bindings requires "numpy" package.')
  13. print('Install it via command:')
  14. print(' pip install numpy')
  15. raise
  16. # TODO
  17. # is_x64 = sys.maxsize > 2**32
  18. def __load_extra_py_code_for_module(base, name, enable_debug_print=False):
  19. module_name = "{}.{}".format(__name__, name)
  20. export_module_name = "{}.{}".format(base, name)
  21. native_module = sys.modules.pop(module_name, None)
  22. try:
  23. py_module = importlib.import_module(module_name)
  24. except ImportError as err:
  25. if enable_debug_print:
  26. print("Can't load Python code for module:", module_name,
  27. ". Reason:", err)
  28. # Extension doesn't contain extra py code
  29. return False
  30. if not hasattr(base, name):
  31. setattr(sys.modules[base], name, py_module)
  32. sys.modules[export_module_name] = py_module
  33. # If it is C extension module it is already loaded by cv2 package
  34. if native_module:
  35. setattr(py_module, "_native", native_module)
  36. for k, v in filter(lambda kv: not hasattr(py_module, kv[0]),
  37. native_module.__dict__.items()):
  38. if enable_debug_print: print(' symbol({}): {} = {}'.format(name, k, v))
  39. setattr(py_module, k, v)
  40. return True
  41. def __collect_extra_submodules(enable_debug_print=False):
  42. def modules_filter(module):
  43. return all((
  44. # module is not internal
  45. not module.startswith("_"),
  46. not module.startswith("python-"),
  47. # it is not a file
  48. os.path.isdir(os.path.join(_extra_submodules_init_path, module))
  49. ))
  50. if sys.version_info[0] < 3:
  51. if enable_debug_print:
  52. print("Extra submodules is loaded only for Python 3")
  53. return []
  54. __INIT_FILE_PATH = os.path.abspath(__file__)
  55. _extra_submodules_init_path = os.path.dirname(__INIT_FILE_PATH)
  56. return filter(modules_filter, os.listdir(_extra_submodules_init_path))
  57. def bootstrap():
  58. import sys
  59. import copy
  60. save_sys_path = copy.copy(sys.path)
  61. if hasattr(sys, 'OpenCV_LOADER'):
  62. print(sys.path)
  63. raise ImportError('ERROR: recursion is detected during loading of "cv2" binary extensions. Check OpenCV installation.')
  64. sys.OpenCV_LOADER = True
  65. DEBUG = False
  66. if hasattr(sys, 'OpenCV_LOADER_DEBUG'):
  67. DEBUG = True
  68. import platform
  69. if DEBUG: print('OpenCV loader: os.name="{}" platform.system()="{}"'.format(os.name, str(platform.system())))
  70. LOADER_DIR = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
  71. PYTHON_EXTENSIONS_PATHS = []
  72. BINARIES_PATHS = []
  73. g_vars = globals()
  74. l_vars = locals()
  75. if sys.version_info[:2] < (3, 0):
  76. from . load_config_py2 import exec_file_wrapper
  77. else:
  78. from . load_config_py3 import exec_file_wrapper
  79. def load_first_config(fnames, required=True):
  80. for fname in fnames:
  81. fpath = os.path.join(LOADER_DIR, fname)
  82. if not os.path.exists(fpath):
  83. if DEBUG: print('OpenCV loader: config not found, skip: {}'.format(fpath))
  84. continue
  85. if DEBUG: print('OpenCV loader: loading config: {}'.format(fpath))
  86. exec_file_wrapper(fpath, g_vars, l_vars)
  87. return True
  88. if required:
  89. raise ImportError('OpenCV loader: missing configuration file: {}. Check OpenCV installation.'.format(fnames))
  90. load_first_config(['config.py'], True)
  91. load_first_config([
  92. 'config-{}.{}.py'.format(sys.version_info[0], sys.version_info[1]),
  93. 'config-{}.py'.format(sys.version_info[0])
  94. ], True)
  95. if DEBUG: print('OpenCV loader: PYTHON_EXTENSIONS_PATHS={}'.format(str(l_vars['PYTHON_EXTENSIONS_PATHS'])))
  96. if DEBUG: print('OpenCV loader: BINARIES_PATHS={}'.format(str(l_vars['BINARIES_PATHS'])))
  97. applySysPathWorkaround = False
  98. if hasattr(sys, 'OpenCV_REPLACE_SYS_PATH_0'):
  99. applySysPathWorkaround = True
  100. else:
  101. try:
  102. BASE_DIR = os.path.dirname(LOADER_DIR)
  103. if sys.path[0] == BASE_DIR or os.path.realpath(sys.path[0]) == BASE_DIR:
  104. applySysPathWorkaround = True
  105. except:
  106. if DEBUG: print('OpenCV loader: exception during checking workaround for sys.path[0]')
  107. pass # applySysPathWorkaround is False
  108. for p in reversed(l_vars['PYTHON_EXTENSIONS_PATHS']):
  109. sys.path.insert(1 if not applySysPathWorkaround else 0, p)
  110. if os.name == 'nt':
  111. if sys.version_info[:2] >= (3, 8): # https://github.com/python/cpython/pull/12302
  112. for p in l_vars['BINARIES_PATHS']:
  113. try:
  114. os.add_dll_directory(p)
  115. except Exception as e:
  116. if DEBUG: print('Failed os.add_dll_directory(): '+ str(e))
  117. pass
  118. os.environ['PATH'] = ';'.join(l_vars['BINARIES_PATHS']) + ';' + os.environ.get('PATH', '')
  119. if DEBUG: print('OpenCV loader: PATH={}'.format(str(os.environ['PATH'])))
  120. else:
  121. # amending of LD_LIBRARY_PATH works for sub-processes only
  122. os.environ['LD_LIBRARY_PATH'] = ':'.join(l_vars['BINARIES_PATHS']) + ':' + os.environ.get('LD_LIBRARY_PATH', '')
  123. if DEBUG: print("Relink everything from native cv2 module to cv2 package")
  124. py_module = sys.modules.pop("cv2")
  125. native_module = importlib.import_module("cv2")
  126. sys.modules["cv2"] = py_module
  127. setattr(py_module, "_native", native_module)
  128. for item_name, item in filter(lambda kv: kv[0] not in ("__file__", "__loader__", "__spec__",
  129. "__name__", "__package__"),
  130. native_module.__dict__.items()):
  131. if item_name not in g_vars:
  132. g_vars[item_name] = item
  133. sys.path = save_sys_path # multiprocessing should start from bootstrap code (https://github.com/opencv/opencv/issues/18502)
  134. try:
  135. del sys.OpenCV_LOADER
  136. except Exception as e:
  137. if DEBUG:
  138. print("Exception during delete OpenCV_LOADER:", e)
  139. if DEBUG: print('OpenCV loader: binary extension... OK')
  140. for submodule in __collect_extra_submodules(DEBUG):
  141. if __load_extra_py_code_for_module("cv2", submodule, DEBUG):
  142. if DEBUG: print("Extra Python code for", submodule, "is loaded")
  143. if DEBUG: print('OpenCV loader: DONE')
  144. bootstrap()