Additional Rhino 6 GhPython feedback

Have you ever tried using a windows console to output?:

Execute this once from the Rhino Python console:

import System
import System.IO as io
from System import Console
import Microsoft.Win32.SafeHandles as sh
import ctypes as ct

stdOutputHandle = ct.c_int(-11)
ct.windll.kernel32.AllocConsole()
intPt = ct.windll.kernel32.GetStdHandle(stdOutputHandle)
stdHandle = System.IntPtr(intPt)
safeFileHandle = sh.SafeFileHandle(stdHandle, True)
fileStream = io.FileStream(safeFileHandle, io.FileAccess.Write)
encoding = System.Text.Encoding.GetEncoding(437)
standardOutput = io.StreamWriter(fileStream, encoding)
standardOutput.AutoFlush = True
Console.SetOut(standardOutput)
Console.WriteLine(“This is a console window”)

and this from a GH Python or Rhino Python script:

from System import Console

Console.WriteLine(“Hi from Grasshopper”)



3 Likes

I have indeed, when executing .py files through the python.exe (as a rudimentary input/output UI) and for C++ development.

Edit: Not that I would consider the Windows console as a valid solution/workaround in any way, it is also not close to the performance of e.g. Sublime and GHPython in Rhino 5:

1 Like

Sorry, please allow me to repeat.

GhPython can have results extracted via normal outputs and that’s far more efficient.

It’s very true. In Sublime, we are in a console application where the only direct output is text. Here, printing is the worst way to output data for Grasshopper. When printing, data needs to be converted to text, flushed into a stream, gathered from the stream, its location within the cycle system needs to be recorded, and finally we can process it as a normal Grasshopper text output. This means that all the steps prior to “process as a normal text output” are extra costly. It’s even surprising all this does not take even longer.

I understand that this particular editor tweak (the DataGridView) might not be required for someone like you, who understand the cycles system, has developed for year, and knows what he’s doing. But for many, it’s very very useful. I hope I can develop a way to switch here. We will need to see how important and time-consuming this would be to implement.

This is understandable! Generally, I’d really recommend you explore developing with a professional IDE, rather than expecting to make the GhPython editor a professional IDE in its own right. The GhPython IDE will never be completely on-par with a professional Python IDE, simply because it’s part of a 3D modeling program and it has a more-circumscribed purpose*.

Do you know about the new option to debug within GhPython with an external IDE? This really makes using another IDE a solid option, even better than GhPython itself. This should get you excited**.

Feel free to pin Microsoft about this. I suspect the setting is still there, buried under many layers. It was certainly there in Windows 8, the last time I checked.

* This does not mean that we will not improve it. In fact, some improvements are being developed.
** With this, please do not tell me that we only develop for new users! :slight_smile: It’s already in Rhino WIP.

That would be an ideal solution.

I’ve continuously been stating (and am expecting) the exact opposite of GHPython:

My point was that adding the type of bloat (as I see it) that has crept into the new editor, is a move towards the bloat and sluggishness I would expect from a full IDE. I wouldn’t consider adding the DataGridView a tweak, but a major modification (in that direction).

Yeah :roll_eyes:

I feel like I’m not really getting through here. So I think I’ll just Homer into the bushes at this point.

Best,

Anders

I have read more about that Console issue, and its known that the default microsoft console is pretty slow. I think it might be an option to elaborate using Bash (like Git), which is supposed to work much faster. But in the end the point remains, why printing 10000+ of lines? Please don’t get me wrong, because I really think you are a great develloper, but what about writing unit and integration tests instead of outputing that many data and check per eye? I just recently established an full continous integration for the software I currently develop. And its astonishing how many bugs are prevented, just by writing tests, line covering nearly up to 100% of (testable) code. I believe chances are way higher to miss an error by eye-scanning then by asserting it from a test routine. Test Driven Devolopement, is slow and sometimes annoying, but the benefit is really great.

1 Like

I think you’re right to expect this. I doubt we’ll make any drastic changes in V6 for the code editing experience, but it is something that we are trying to improve in V7.


I’ll need to read through the rest of this post as I just became aware of it.

1 Like

No worries, and likewise. I don’t consider myself a developer as such. I’m a designer that employs computation as my primary medium, with the intention of solving “design problems as fast and agile as I can. If my intention was to write “real” components I’d be in Visual Studio” (douchely quoting myself from the type hint topic). GHPython has been absolutely terrific in supporting this type of development:

Using an external IDE, writing unit tests etc. quite simply adds unnecessary complexity and layers of dependencies to this (i.e. mine) development environment. Which occurs across several machines, several teams, dealing with an IT department etc. In what can only described as being a very high pace.

One of the things I’ve neglected to mention here actually (apologies), is that upgrading GHPython be a standard component in Rhino 6 (along with Kangaroo!) has really helped tremendously :ok_hand:

3 Likes

I’d love to see a toggle for this. I am not sure I understand what cycles system mean putting myself in the latter group. Still I don’t think DataGridView has a place as an output console. More like for example the Hydrostatics command results that best fits being tabular.
Simply put, since I don’t always know what I’m doing with GhPython I use a lot of printing checking for types and results. Sometimes I need to select a piece of what’s in the console in order to search for it in the API and currently that’s difficult, or requires additional steps (copy to notepad and selecting just a piece of the string).

1 Like

This is the drawback of a dynamic typed language. The time you save when not writing the type of an variable, just begins to add up in the end, by checking whats actually in there. Especially if you mix that with a framework developed for a rather strongly typed language - just as IronPython does with the .Net-Framework. Confusion just becomes perfect (f.e. Interfaces such as IEnumerable, access modifier …).
I guess that is also one of the reasons, Ironpython is actually a legacy system… I would have had a much harder time with IronPython, if I not knew C# (or .VB.Net alternativly). I can guess that its lots of work, but rewriting the Rhinocommon wrapper, to support CPython, would probably solve many of these problems at the end, because having the need for a good console log is probaly just the result of this confusion…

1 Like

Oh no, I don’t think so, I spent even more time printing stuff when I work in pure C#. At least in Python I can easily figure out my errors by simple printing.

Perhaps this is a problem between the chair and the keyboard, but I find the printing output in this editor difficult to use. I use this all day and regularly work on meshes that have anywhere from 10,000 - 300,000 faces. I have issues when printing only a few hundred items in this editor, which means I am constantly dancing around to be careful of printing the wrong thing, for fear of the canvas freezing up.

Also… it is very difficult to explore python modules with dir() because there is no line numbering or line breaks on the printed output. This makes it especially difficult to navigate ghenv, which so far as I know has no other form of documentation.

I’ve been quietly crossing my fingers. But as far as I can tell, none of these issues (nor the default type hint one) have been addressed in the Rhino 7 Beta. While I gather that effort is being put into developing a better scripting experience/editor across Rhino in general. It’s quite disappointing to (potentially) have to deal with a broken GHPython editor till Rhino 8 (or later) :expressionless:

As a refresher on issue number 1, try going print range(1000000) in Rhino 5, then Rhino 7 Beta.

I currently develop software on a daily base and I almost never print anything to a console anymore. If you want a log, you write a log file. If you want to validate, you write a unit test. If you want to check the logic you set a (conditional) breakpoint and step through the code. If you want to spot memory leaks or performance issues you use a profiler. Scriping has limitations and even the best script editor does not replace an advanced code editor or even IDE.
On the other hand, writing code without that, really helps in memorizing an api. And once you can write fluent Rhinocommon, developing is really fun.

None of that addresses the fact that the new GHPython (console) is broken. Please refrain from diverging attention away from that (especially if you do not use the GHPython component). We just want to print to the console while we write Python code in Grasshopper. Why is that so hard to accept?

Its not hard to accept that at all. Besides this I use the GHPython Component from time to time. I just doubt that printing thousands of lines to a pseudo console is a good way of debugging. Logging to a file persist the information, even if the app crashes. It also makes it possible to compare results later.
Stepping through code and writing test routines, makes sure the logic works without going through the whole script. And a profiler tells you if you do things efficently without any leaks.

1 Like

Yeah, it sounds like you are a pretty advanced user. I am learning each of these techniques and I’m sure I will find ways to work around this problem as I move forward… but the point is that I am dancing around something here. The console used to be able to handle this in light and reliable way (in Rhino 5) and it doesn’t do that any more.

2 Likes

I know that @Alain has been working on improving the print output editor in a way that addressed your concerns. In Rhino 7 BETA, you can now choose to print the output as simple text. Also, copy-paste should now be simpler. I specifically asked this to be shipped with Rhino 7 SR0.

The default type hint was deliberately left as rhinoscriptsyntax. You can create your own defaults for this using a Grasshopper User Object. A GHUO can store default code, default type hints and default variable names both for input and outputs. It also stores the default window position and a few other minor settings. It stores also SDK mode ON/OFF. We can have it store more stuff if you need. Personally, maybe I’d like it to store font size.

2 Likes

That’s fantastic news! I only just quickly tested the Rhino 7 Beta and must have missed this. Many many apologies, should have looked closer. And setting this option appears to be persistent, again this is just awesome guys :clap:

Whoaah, that sounds like great news as well. How does that work when adding new input parameters via ZUI?

Also only just noticed AutoSolve :open_mouth:

In Rhino 6 you can replace the output as well. In case the DataGrid is the bottleneck here. In theory you can replace the label with any other usercontrol.

Here is a quick proof of concept. (It replaces the output grid with a simple text label)

import System.Reflection as rf
import System.Windows.Forms as forms

def print_ex(line):
    editor = ghdoc.Component.Attributes.Form
    outputPage = editor.GetType().GetField("outputPage", rf.BindingFlags.NonPublic | rf.BindingFlags.Instance).GetValue(editor);
    label = forms.Label()
    label.Text = line
    outputPage.Controls.Clear()
    outputPage.Controls.Add(label)
    outputPage.SuspendLayout();

print_ex("foobar")

The reflection call could be made only once per script execution, since this will be a potential bottleneck.

@AndersDeleuran @Alexander_Jacobson

Here is the workaround for RH6. Works extremly fast compared to the inbuild one. Give it a try. Of course its visible to the user, and I spend no time in making it more reliable or nice. But see it as quick solution.

"""Provides a scripting component.
    Inputs:
        x: The x script variable
        y: The y script variable
    Output:
        a: The a output variable"""

__author__ = "tomja"
__version__ = "2020.10.14"

import rhinoscriptsyntax as rs

from System.Text import StringBuilder
import System.String as ss
import System.Reflection as rf
import System.Windows.Forms as forms

outputPage = None
textBox = None
printdata = StringBuilder()
def print_f(line):
    global outputPage, textBox    
    if (outputPage == None and textBox == None):
        editor = ghdoc.Component.Attributes.Form
        outputPage = editor.GetType().GetField("outputPage", rf.BindingFlags.NonPublic | rf.BindingFlags.Instance).GetValue(editor);
        outputPage.Controls.Clear()
        textBox = forms.TextBox()
        textBox.Width = 1200
        textBox.Height = 200
        textBox.Multiline = True
        textBox.ScrollBars = forms.ScrollBars.Vertical
        textBox.AcceptsReturn = True
        textBox.AcceptsTab = True
        textBox.WordWrap = True
        outputPage.Controls.Add(textBox)
        outputPage.SuspendLayout()
        
    printdata.Append(line)

# Your code goes in here
for i in range(0,100000):
    print_f("test \r\n") 


# Add to the output before the script terminates
textBox.Text = printdata.ToString()
3 Likes