Oct-06-2023, 09:38 AM
I don't know where to make such a suggestion, so I'm bringing the topic up on this forum.
In short, I have a proof of concept that allows a user to split an import off into another thread so that loading the import does not interfere with the flow of the software (in the context of GUI-based software, every second waiting makes your product look worse).
I am proposing that a similar concept is implemented withing the importlib to make this functionality easy for all programmers - especially in a GIL-free context (coming soon). It works by importing the module using a string of its name, importing the module in an alternative thread and then activating the import when .join() is called (will either be instantaneous or will wait for the import to complete). Calling .join() will overwrite the object dictionary of the import class using the dictionary from the import.
I use sentence_transformers as an example because it loads Pytorch (an 800 MB C library), and therefore not only demonstrates the proof of concept but shows its use in developing AI-based GUI applications.
In short, I have a proof of concept that allows a user to split an import off into another thread so that loading the import does not interfere with the flow of the software (in the context of GUI-based software, every second waiting makes your product look worse).
I am proposing that a similar concept is implemented withing the importlib to make this functionality easy for all programmers - especially in a GIL-free context (coming soon). It works by importing the module using a string of its name, importing the module in an alternative thread and then activating the import when .join() is called (will either be instantaneous or will wait for the import to complete). Calling .join() will overwrite the object dictionary of the import class using the dictionary from the import.
I use sentence_transformers as an example because it loads Pytorch (an 800 MB C library), and therefore not only demonstrates the proof of concept but shows its use in developing AI-based GUI applications.
from threading import Thread import time class SplitImport(Thread): def __init__(self, name:str = None) -> None: self.target = __import__ Thread.__init__(self, None, self.target, name, (name,), {}) self._return = None self.name = name self.start() #? New thread starts automatically def run(self): if self.target is not None: self._return = self._target(*self._args) def join(self, *args): '''The join method has been modified to return True once complete. Join has to be called in order to overwrite the Thread Object with the Import dictionary.''' Thread.join(self, *args) #* Rewrite object dictionary _import = self._return self.__dict__ = dict() self.__dict__.update(_import.__dict__) # Insert isimported method def isimported(self): return True self.isimported = isimported return "Joined" def isimported(self): return False #* TIMING AND TESTING *# start_time = time.perf_counter() # Initialise split import sentence_transformers = SplitImport("sentence_transformers") # Check time taken to start thread print("Import statement pass time:", time.perf_counter()-start_time) # Check original dictionary print(sentence_transformers.__dict__) # Activate import print(sentence_transformers.join()) # Check that new atrributes are available print(sentence_transformers.__dict__) # Check total import time (including two print statements) print("Import statement execution time:", time.perf_counter()-start_time)