diff --git a/src/python/nimbusml/internal/utils/entrypoints.py b/src/python/nimbusml/internal/utils/entrypoints.py index 1f030443..bcdc325d 100644 --- a/src/python/nimbusml/internal/utils/entrypoints.py +++ b/src/python/nimbusml/internal/utils/entrypoints.py @@ -22,7 +22,8 @@ from .data_stream import FileDataStream from .dataframes import resolve_dataframe, resolve_csr_matrix, pd_concat, \ resolve_output -from .utils import try_set, set_clr_environment_vars, get_clr_path +from .utils import try_set, set_clr_environment_vars, get_clr_path, \ + get_nimbusml_libs from ..libs.pybridge import px_call @@ -445,15 +446,11 @@ def remove_multi_level_index(c): 'graph = {%s} %s' % (str(self), code), False, str) - # Set paths to ML.NET binaries (in nimbusml) and to .NET Core CLR binaries - nimbusml_path = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', 'libs')) - call_parameters['nimbusmlPath'] = try_set(nimbusml_path, True, str) - call_parameters['dotnetClrPath'] = try_set(nimbusml_path, True, str) - # dotnetcore2 package is available only for python 3.x - if six.PY3: - set_clr_environment_vars() - call_parameters['dotnetClrPath'] = try_set(get_clr_path(), True, str) + # Set paths to ML.NET libs (in nimbusml) and to .NET Core CLR libs + call_parameters['nimbusmlPath'] = try_set(get_nimbusml_libs(), True, str) + set_clr_environment_vars() + call_parameters['dotnetClrPath'] = try_set(get_clr_path(), True, str) + if random_state: call_parameters['seed'] = try_set(random_state, False, int) ret = self._try_call_bridge( diff --git a/src/python/nimbusml/internal/utils/utils.py b/src/python/nimbusml/internal/utils/utils.py index 62def151..848b76b8 100644 --- a/src/python/nimbusml/internal/utils/utils.py +++ b/src/python/nimbusml/internal/utils/utils.py @@ -283,38 +283,55 @@ def set_clr_environment_vars(): Set system environment variables required by the .NET CLR. Python 3.x only, as dotnetcore2 is not available for Python 2.x. """ - from dotnetcore2 import runtime as clr_runtime - dependencies_path = None - try: - # try to resolve dependencies, for ex. libunwind - dependencies_path = clr_runtime.ensure_dependencies() - except: + if six.PY2: pass - os.environ['DOTNET_SYSTEM_GLOBALIZATION_INVARIANT'] = 'true' - if dependencies_path is not None: - os.environ['LD_LIBRARY_PATH'] = dependencies_path + else: + from dotnetcore2 import runtime as clr_runtime + dependencies_path = None + try: + # try to resolve dependencies, specifically libunwind for Linux + dependencies_path = clr_runtime.ensure_dependencies() + except: + pass + # Without this, Linux versions would require the ICU package + os.environ['DOTNET_SYSTEM_GLOBALIZATION_INVARIANT'] = 'true' + # Will be None for Windows + if dependencies_path is not None: + os.environ['LD_LIBRARY_PATH'] = dependencies_path def get_clr_path(): """ - Return path to .NET CLR binaries. - Python 3.x only, as dotnetcore2 is not available for Python 2.x. + Return path to .NET CLR libs. + Use dotnetcore2 package if Python 3.x, otherwise look for libs bundled with + NimbusML. """ - from dotnetcore2 import runtime as clr_runtime - clr_version = pkg_resources.get_distribution('dotnetcore2').version - partial_path = os.path.join(clr_runtime._get_bin_folder(), 'shared', 'Microsoft.NETCore.App') - clr_path = os.path.join(partial_path, clr_version) - if not os.path.exists(clr_path): - # If folder name does not match published version, use the folder that - # exists - try: - version_folder = os.listdir(partial_path)[0] - except IndexError: + if six.PY2: + return get_nimbusml_libs() + else: + from dotnetcore2 import runtime as clr_runtime + libs_root = os.path.join(clr_runtime._get_bin_folder(), 'shared', + 'Microsoft.NETCore.App') + + # Search all libs folders to find which one contains the .NET CLR libs + libs_folders = os.listdir(libs_root) + if len(libs_folders) == 0: raise ImportError("Trouble importing dotnetcore2: " - "{} had no version folder.".format(partial_path)) - clr_path = os.path.join(partial_path, version_folder) - # Verify binaries are present - if not os.path.exists(os.path.join(clr_path, 'Microsoft.CSharp.dll')): + "{} had no libs folders.".format(libs_root)) + clr_path = None + for folder in libs_folders: + if os.path.exists(os.path.join(libs_root, folder, + 'Microsoft.CSharp.dll')): + clr_path = os.path.join(libs_root, folder) + break + if not clr_path: raise ImportError( "Trouble importing dotnetcore2: Microsoft.CSharp.dll was not " - "found in {}.".format(clr_path)) - return clr_path \ No newline at end of file + "found in {}.".format(libs_root)) + return clr_path + +def get_nimbusml_libs(): + """ + Return path to NimbusML libs (the ML.NET binaries). + """ + return os.path.abspath(os.path.join(os.path.dirname(__file__), '..', + 'libs'))