I see that I slightly lost track of the fact that you want to look at 
ongoing error messages.  As I said, the big problem that I am aware of is 
that the message pipe fills up and then blocks quickly.  That suggests that 
a thread or other process should read it frequently to allow new data to be 
inserted.  I do remember that there is some discussion on line - not 
necessarily Python-specific - to be found.

On Thursday, May 4, 2023 at 12:11:50 AM UTC-4 Thomas Passin wrote:

> I don't know the answer but I know a thing or two that might be useful.  
> By starting the command with "&", as you have, you avoid 
> the proc.communicate() call, which would block Leo until it returns.  
> However, if you try to capture output with a pipe, the pipe can block if it 
> fills up, and that happens with a surprisingly small number of bytes.  Then 
> you block because the pipe is waiting to be cleared, and you are probably 
> waiting to get output from the pipe.
>
> So that won't work.  
>
> The way I managed this with the background process manager (BPM) - it's 
> what launches pylint, mypy, etc - is to use a separate thread to launch the 
> process, and call proc.communicate() in that thread.  The thread blocks 
> waiting for the process to complete, but that doesn't matter since it 
> doesn't block Leo itself.  This leaves the question of how to get the 
> results.  The thread puts the results into a variable in the BPM, and the 
> BPM registers a callback at idle time.  The callback checks to see if the 
> variable is not None. If the BPM sees that there is a result in that 
> variable, it cancels the callback and makes use of the result.  Then it 
> writes the messages to the log pane.  You have to use a lock to make sure 
> that the external process's results are put atomically into the variable. 
> In your case I might have it write the results to a different tab to avoid 
> getting mixed up with regular log output. I'm going by memory here and 
> might have a detail or two inaccurate.
>
> So study the BPM and see if you could do something similar with your 
> code.  The BPM makes sure that it only ever runs one process at a time, 
> BTW. That avoids the possibility of getting intermingled results or other 
> confusions.
>
> Another possibility is to have your external process redirect output to a 
> known file.  You could check periodically to see if that file has gotten 
> new data and read the new data if so.  The problem there might be to know 
> when the external process is finished writing data.  You could also hget a 
> race condition between the writing process and the reading process, so you 
> would have to figure out how to handle that situation.  I don't happen to 
> know how that works and it might be different between Windows and Linux.
>
> Another possibility would be to launch your external program from a 
> batch/shell file and have the batch/shell file redirect the output to a 
> known file.  When the programs finishes, the batch file could set an 
> environmental variable.  You could do the idle-time callback trick to check 
> for that variable, or you could have the checks done periodically by a 
> separate thread.  That thread could even read the results, format them, and 
> write them to a new tab or pass them on to another batch file.
>
> I would say the last possibility sounds the most promising to me.
>
>
>
> On Wednesday, May 3, 2023 at 7:02:47 PM UTC-4 gates...@gmail.com wrote:
>
>> Hi all,
>>
>> I have an outline with some @button nodes that fire off external shell 
>> commands using g.execute_shell_commands.  I tend to run Leo *without* a 
>> console window open, so anything those @button-triggered shell commands 
>> print to the console is lost to me.  Is there an easy way/straightforward 
>> way to redirect to the stdout/stderr for those commands only to the log 
>> pane?  I'm struggling to figure it out by manipulating sys.stdout and 
>> sys.stderr, though I admit this is far from my area of specialty.
>>
>> An example of a button:
>>
>> ```
>> @language python
>> @tabwidth -2
>>
>> ''' Executes the currently selected sketch with the 'vsk run' command.
>> '''
>>
>> import os.path
>>
>> fn = c.getNodeFileName(p)
>> if len(fn) == 0:
>>   # non-external file selected
>>   g.es('Not a valid sketch node.', color='red')
>>
>> else:
>>   sketch_path = os.path.dirname(fn)
>>   g.execute_shell_commands(f'&vsk run {sketch_path}')
>> ```
>>
>> That command is long-running (i.e. it stays open in another pane, thus 
>> the '&' to unblock the Leo GUI).  Sometimes it indicates errors on the 
>> console output, which just plain doesn't exist when I'm running Leo without 
>> a console window open.
>>
>> Ideally any solution would be cross-platform, since I do this on both 
>> Windows and Linux... but really I'd be happy with platform-specific 
>> solutions too.  I'd really rather not have to have a console window open to 
>> see these errors if at all possible.
>>
>> Thanks in advance for any ideas and suggestions,
>> Jake
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/af4bc586-34e4-442d-980e-6389da6af39en%40googlegroups.com.

Reply via email to