2020using System . Reflection ;
2121using System . Runtime . InteropServices ;
2222using System . Security . Policy ;
23+ using Python . Runtime ;
2324using QuantConnect . Interfaces ;
2425using QuantConnect . Logging ;
2526using QuantConnect . AlgorithmFactory . Python . Wrappers ;
27+ using QuantConnect . Configuration ;
2628using QuantConnect . Python ;
2729using QuantConnect . Util ;
2830
@@ -34,6 +36,9 @@ namespace QuantConnect.AlgorithmFactory
3436 [ ClassInterface ( ClassInterfaceType . AutoDual ) ]
3537 public class Loader : MarshalByRefObject
3638 {
39+ // True if we are in a debugging session
40+ private readonly bool _debugging ;
41+
3742 // Defines the maximum amount of time we will allow for instantiating an instance of IAlgorithm
3843 private readonly TimeSpan _loaderTimeLimit ;
3944
@@ -70,13 +75,14 @@ public class Loader : MarshalByRefObject
7075 /// Creates a new loader with a 10 second maximum load time that forces exactly one derived type to be found
7176 /// </summary>
7277 public Loader ( )
73- : this ( Language . CSharp , TimeSpan . FromSeconds ( 10 ) , names => names . SingleOrDefault ( ) )
78+ : this ( false , Language . CSharp , TimeSpan . FromSeconds ( 10 ) , names => names . SingleOrDefault ( ) )
7479 {
7580 }
7681
7782 /// <summary>
7883 /// Creates a new loader with the specified configuration
7984 /// </summary>
85+ /// <param name="debugging">True if we are debugging</param>
8086 /// <param name="language">Which language are we trying to load</param>
8187 /// <param name="loaderTimeLimit">
8288 /// Used to limit how long it takes to create a new instance
@@ -89,8 +95,9 @@ public Loader()
8995 /// that's what this function does, it picks the correct type from the list of types found within the assembly.
9096 /// </param>
9197 /// <param name="workerThread">The worker thread instance the loader should use</param>
92- public Loader ( Language language , TimeSpan loaderTimeLimit , Func < List < string > , string > multipleTypeNameResolverFunction , WorkerThread workerThread = null )
98+ public Loader ( bool debugging , Language language , TimeSpan loaderTimeLimit , Func < List < string > , string > multipleTypeNameResolverFunction , WorkerThread workerThread = null )
9399 {
100+ _debugging = debugging ;
94101 _language = language ;
95102 _workerThread = workerThread ;
96103 if ( multipleTypeNameResolverFunction == null )
@@ -159,28 +166,20 @@ private bool TryCreatePythonAlgorithm(string assemblyPath, out IAlgorithm algori
159166 var pythonFile = new FileInfo ( assemblyPath ) ;
160167 var moduleName = pythonFile . Name . Replace ( ".pyc" , "" ) . Replace ( ".py" , "" ) ;
161168
162- // Set the python path for loading python algorithms.
163- var pythonPath = new List < string >
164- {
165- pythonFile . Directory . FullName ,
166- new DirectoryInfo ( Environment . CurrentDirectory ) . FullName ,
167- } ;
168-
169- // Don't include an empty environment variable in pythonPath, otherwise the PYTHONPATH
170- // environment variable won't be used in the module import process
171- var pythonPathEnvironmentVariable = Environment . GetEnvironmentVariable ( "PYTHONPATH" ) ;
172- if ( ! string . IsNullOrEmpty ( pythonPathEnvironmentVariable ) )
173- {
174- pythonPath . Add ( pythonPathEnvironmentVariable ) ;
175- }
176-
177- Environment . SetEnvironmentVariable ( "PYTHONPATH" , string . Join ( OS . IsLinux ? ":" : ";" , pythonPath ) ) ;
178-
179169 try
180170 {
181171 PythonInitializer . Initialize ( ) ;
182172
183173 algorithmInstance = new AlgorithmPythonWrapper ( moduleName ) ;
174+
175+ // we need stdout for debugging
176+ if ( ! _debugging && Config . GetBool ( "mute-python-library-logging" , true ) )
177+ {
178+ using ( Py . GIL ( ) )
179+ {
180+ PythonEngine . Exec ( "import os, sys; sys.stdout = open(os.devnull, 'w')" ) ;
181+ }
182+ }
184183 }
185184 catch ( Exception e )
186185 {
0 commit comments