iqrf 3 Posted May 29, 2023 Hello, is it possible to somehow create a submodule. Something like this MainModule := TPythonModule.Create(nil); MainModule.ModuleName := 'spam'; SubModule := TPythonModule.Create(nil); SubModule.ModuleName := 'spam.test'; and call in Python import spam import spam.test spam.function1() spam.test.function2() it reports an error if i do it like this it's fine import spam import spam.test as T spam.function1() T.function2() Can it be solved somehow? Thanks for the ideas. Share this post Link to post
PingPIng 23 Posted May 30, 2023 16 hours ago, iqrf said: Hello, is it possible to somehow create a submodule. Something like this MainModule := TPythonModule.Create(nil); MainModule.ModuleName := 'spam'; SubModule := TPythonModule.Create(nil); SubModule.ModuleName := 'spam.test'; and call in Python import spam import spam.test spam.function1() spam.test.function2() it reports an error if i do it like this it's fine import spam import spam.test as T spam.function1() T.function2() Can it be solved somehow? Thanks for the ideas. PythonModule1 := TPythonModule.Create(nil); PythonModule1.Engine := GetPythonEngine ; PythonModule1.ModuleName := 'call'; PythonModule1.AddDelphiMethod('preprocess',preprocess,'This function pre-processes data.'); PythonModule1.MakeModule; function Disassembler.preprocess(pself, args: PPyObject): PPyObject; cdecl; var op_data, Dis_data: PPyObject; opcode_sequences, disasm_sequences, opcode_input_data, disasm_input_data: Variant; begin with GetPythonEngine do begin if PyArg_ParseTuple(args, 'OO', @op_data, @Dis_data) <> 0 then begin var bm := BuiltinModule(); var p_op_data := VarPythonCreate(op_data); var p_Dis_data:= VarPythonCreate(Dis_data); var b :=bm.type(opcode_tokenizer); // Preprocess data here as shown above opcode_sequences := opcode_tokenizer.texts_to_sequences(p_op_data); disasm_sequences := disasm_tokenizer.texts_to_sequences(p_Dis_data); opcode_input_data := t_tf.tf.keras.preprocessing.sequence.pad_sequences(opcode_sequences, maxlen:=Fopcode_seq_len) ; disasm_input_data := t_tf.tf.keras.preprocessing.sequence.pad_sequences(disasm_sequences, maxlen:=Fdisasm_seq_len) ; opcode_input_data := t_tf.tf.keras.utils.to_categorical(opcode_input_data, num_classes:=Finput_dim); disasm_input_data := t_tf.tf.keras.utils.to_categorical(disasm_input_data, num_classes:=Foutput_dim); Result := VariantAsPyObject( TPyEx.Tuple([opcode_input_data, disasm_input_data]) ); end else Result := nil; end; end; Share this post Link to post
iqrf 3 Posted May 30, 2023 Thanks, but understanding this code is beyond my abilities. Share this post Link to post
KoRiF 1 Posted May 31, 2023 I'm afraid to add a submodule you have to go beyond Python4Delphi components and use Python C-API try to study how the TPythonModule instance is created and act similarly You will need to modify this approach someway to add the submodule entry to the dictionary for the supermodule: try use PythonEngine.PyModule_GetDict(PythonModule.Module) https://github.com/pyscripter/python4delphi/blob/1cd66211f586468d9fe3a1352344073759e64d8a/Source/PythonEngine.pas#L3655 Check also: https://github.com/pyscripter/python4delphi/blob/master/Source/PythonEngine.pas#L3649 https://python.readthedocs.io/en/stable/c-api/import.html?highlight=pyimport_getmoduledict#c.PyImport_GetModuleDict https://python.readthedocs.io/en/stable/c-api/import.html#c.PyImport_AddModuleObject this will require some experimentation, but I hope you succeed Share this post Link to post
iqrf 3 Posted June 1, 2023 Hi, I finally solved it at the Python level. I have two TPython modules, one named main_module and the other sub_module. Just add to the InitScript import main_module import sub_module main_module.sub_module = sub_module And you can use in Python main_module.sub_module.function1() but of course, also sub_module.function1(). In this way, a pseudo-hierarchical structure of modules can be created. Because this doesn't import main_module.sub_module as a test. main_module is not a package! Share this post Link to post
iqrf 3 Posted June 1, 2023 I finally found a way to make a package import importlib import types import sys # Package name package_name = 'my_package' # List of modules to be part of the package module_names = ['module1', 'module2'] # Create an empty package package = types.ModuleType(package_name) package.__path__ = [] # Import and add individual modules to the package for module_name in module_names: module = importlib.import_module(module_name) setattr(package, module_name, module) # Set __all__ to the list of module names package.__all__ = module_names # Add the package to the list of imported modules sys.modules[package_name] = package Then it is possible import my_package from my_package import module1 from my_package import module2 as T print(dir(module1)) print(dir(my_package.module1)) print(dir(T)) Only this import my_package.module1 as T is not possible. ModuleNotFoundError: No module named 'my_package.sub_module1' Does anyone know why? Share this post Link to post