Difference between revisions of "User:Orso.b.schmid"

From Vectorworks Developer
Jump to: navigation, search
(add documentation about python caching)
(Vectorlab Archives)
 
(14 intermediate revisions by one user not shown)
Line 1: Line 1:
 +
<div class="rightmenu">
 +
__TOC__
 +
</div>
 +
 
Ciao,
 
Ciao,
  
I am Orso, an Italian Vectorscripter since many years. I feel very comfortable with Vectorscript (from now on: VS) but will now switch over to Python for even more power.
+
I am Orso, an Italian Vectorscripter since many years. Some of you might know me from Vectorlab or the comments on the present Developer wiki. I feel very comfortable with Vectorscript but will now switch over to Python for even more power. I will try to share here comments, problems -and solutions- from the point of view of a non-programmer. --[[User:Orso.b.schmid|Orso.b.schmid]] ([[User talk:Orso.b.schmid|talk]]) 08:13, 17 May 2015 (EDT)
I will try to share here comments, problems -and solutions- from the point of view of a non-programmer. --[[User:Orso.b.schmid|Orso.b.schmid]] ([[User talk:Orso.b.schmid|talk]]) 08:13, 17 May 2015 (EDT)
+
  
Open the terminal on your Mac and write
+
If you add comments, please use the full wiki formatting, easily available clicking on ''Advanced'' while on edit mode and don't forget to sign up your comment using <nowiki>--~~~~</nowiki>!
python
+
try snippets there (or in an editor of your choice if you prefer)
+
  
== Lists ==
+
== Vectorlab Archives ==
 +
Here is the List Browsers article from the now dead Vectorlab site:
 +
* List Browsers ([[:Media:Vectorlab_ListBrowsers_WebArchives.zip| Vectorlab ListBrowsers Web Archives.zip]])
  
Lists are powerful in Python, below some fascinating lists manipulations. They remind me of Applescript:
+
I stored some of the Vectorlab sites:
<code lang="py">
+
months = "Jan Feb Mar Apr May Jun Jul"
+
months = months.split() # no splitter defined and it will use the empty space --> ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul']
+
months[2] # --> 'Mar' note that the index is 0-based
+
months2 = "Jan, Feb, Mar, Apr, May, Jun, Jul"
+
months2.split(', ') # --> ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'] use comma and empty space as splitter
+
months.append('Jul') # --> ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'] append adds an item to a list
+
months.pop() #- -> 'Jul' pop fetches the last item of a list
+
', sunny '.join(months) # --> ', sunny Jan, sunny Feb, sunny Mar, sunny Apr, sunny May, sunny Jun, sunny Sep'
+
'-'.join(months[1:3]) # --> 'Feb-Mar'
+
del months[2] # --> ['Jan', 'Feb', 'Apr', 'May', 'Jun', 'Jul']
+
months = {1: 'Jan', 2: 'Feb', 3: 'Mar'} # --> {1: 'Jan', 2: 'Feb', 3: 'Mar'}
+
</code>
+
  
== Increment a var ==
+
== VS <> Py Rosetta Stone ==
So far I have spent a really inordinate amount of time trying to increment a counter from within a calllback routine. In VS one does it like this:
+
  
<code lang="pas">cnt := cnt +1; { variable cnt is incremented }</code>
+
{| class="wikitable"
 +
! style="width:20%"| Description
 +
! style="width:40%"| Vectorscript
 +
! style="width:40%"| Python
  
For example:
+
|- style="vertical-align: top;"
 +
| '''Statement ending:'''
 +
| '''Semicolon always needed'''
 +
* <code>AlrtDialog('test 1') </br> AlrtDialog('test 2') { error }</code>
 +
* <code>AlrtDialog('test 1'); AlrtDialog('test 2'); { OK }</code>
 +
* <code>AlrtDialog('test 1') AlrtDialog('test 2') { error }</code>
 +
| '''Semicolon needed only for multiple statements on one line:'''
 +
* <code>vs.AlrtDialog('test 1') </br>vs.AlrtDialog('test 2') # OK</code>
 +
* <code>vs.AlrtDialog('test 1'); vs.AlrtDialog('test 2') # OK</code>
 +
* <code>vs.AlrtDialog('test 1') vs.AlrtDialog('test 2') # error</code>
  
<code lang="pas">
+
Error Message: SyntaxError: invalid syntax
PROCEDURE Test;
+
VAR
+
    cnt : INTEGER; { variable scope here is global for this script }
+
  
     { callback subroutine fitting ForEachObject }
+
|- style="vertical-align: top;"
     PROCEDURE DoSomething(h: HANDLE);
+
| '''Case sensitivity'''
 +
| '''Not case sensitive:'''
 +
* <code>AlrtDialog('test'); { OK }</code>
 +
* <code>alrtDialog('test'); { OK }</code>
 +
* <code>alrtdialog('test'); { OK }</code>
 +
* <code>ALRTDIALOG('test'); { OK }</code>
 +
| '''Case sensitive:'''
 +
* <code>vs.AlrtDialog('test') # OK </code>
 +
* <code>vs.alrtDialog('test') # error</code>
 +
* <code>vs.alrtdialog('test') # error</code>
 +
* <code>vs.ALRTDIALOG('test') # error</code>
 +
 
 +
Error Message: AttributeError: 'module' object has no attribute 'vs.ALRTDIALOG'
 +
 
 +
|- style="vertical-align: top;"
 +
| '''Empty brakes for functions'''
 +
: don't forget in python the empty brakets for routines without parameters, this rises errors that are so tricky to find.
 +
| '''Can be without brakets'''
 +
* <code>FSActLayer; { no paramters: brakets not needed }</code>
 +
* <code>MySubroutine;</code>
 +
| '''Can't be without brakets'''
 +
* <code>vs.FSActLayer()</code>
 +
* <code>MySubroutine()</code>
 +
 
 +
Error Message: - none! be careful! -
 +
 
 +
|- style="vertical-align: top;"
 +
| '''Empty handles'''
 +
: do pay attention also to the variable scope (see below).
 +
|
 +
* <code>h <> NIL</code>
 +
|
 +
* <code>h != None</code>
 +
* <code>h != vs.Handle() # not inited instance of a handle, how cryptic</code>
 +
 
 +
|- style="vertical-align: top;"
 +
| '''Variable scope'''
 +
: perhaps the largest source of error for the vectorscripter transitioning to python
 +
|
 +
'''Global wins over local:'''
 +
* Variables must be declared
 +
* Subroutines "see" their own variables and those of any parent function/procedure where they are contained.
 +
<code lang="pas">
 +
{ GLOBAL ACCESS }
 +
{ parent of subroutine "Increment" }
 +
PROCEDURE Main;
 +
    VAR
 +
        { good praxis: label globals with "g" }
 +
        gIndex, gNum : INTEGER;
 +
   
 +
     { subroutine }
 +
     PROCEDURE Increment;
 
         BEGIN
 
         BEGIN
             { ... do something }
+
             { gNum is not defined in this subroutine
             cnt := cnt +1; { global variable is incremented }
+
            the parser climbs up parent containers
 +
            until it finds a declaration for the var gNum.
 +
            In this case it can be found in Main }
 +
             gNum := gNum +1;
 +
            SysBeep;
 
         END;
 
         END;
 +
       
 
BEGIN
 
BEGIN
     cnt := 0; { explicit is better than implicit :) }
+
     gNum := 10; { init }
     ForEachObject(DoSomething, (ALL)); { pick objects by criteria, there the variable cnt will increment }
+
     FOR gIndex := 1 TO 10 DO
     AlrtDialog(Concat('Did something ', cnt, ' times.'));
+
        Increment; { increments the variable gNum }
 +
       
 +
     AlrtDialog(Concat(gNum));
 +
{ returns 20 }
 
END;
 
END;
Run(Test);
+
Run(Main);
 +
</code>
 +
|
 +
'''Local wins over global:'''
 +
* Variables must NOT be declared
 +
* Subroutines create automatically a local instance of any used variable.
 +
 +
<code lang="py">
 +
# LOCAL ACCESS
 +
# subroutine
 +
def Increment():
 +
    # gNum is not defined in this subroutine
 +
    # the parser creates a local instance of the var gNum!
 +
    gNum +=1
 +
    vs.SysBeep
 +
 +
gNum = 10 # init
 +
for gIndex in range(1, 10):
 +
    Increment
 +
    # increments the variable gNum
 +
    # but only inside Increment!
 +
   
 +
vs.AlrtDialog(str(gNum))
 +
# returns 10! The global var didn't set
 
</code>
 
</code>
  
How do I get this done in Python? It's not as easy as it looks like. I thought that this would work:
+
<code lang="py">
 +
# GLOBAL ACCESS: CORRECT
 +
# subroutine
 +
def Increment():
 +
    # gNum is not defined in this subroutine
 +
    # tell the parser that you want to edit gNum global!
 +
    global gNum
 +
    gNum +=1
 +
    vs.SysBeep()
 +
 +
gNum = 10 # init
 +
# please observe that the range is NOT 1, 10!
 +
for gIndex in range(0, 10):
 +
    Increment()
 +
    # increments the variable gNum
 +
    # but only inside Increment!
 +
   
 +
vs.AlrtDialog(str(gNum))
 +
# returns 20
 +
</code>
  
<code lang="py">cnt += 1</code>
+
<code lang="py">
 +
# GLOBAL ACCESS: WRONG
 +
# subroutine
 +
def Increment():
 +
    # gNum is not defined in this subroutine
 +
    # tell the parser that you want to edit gNum global!
 +
    global gNum
 +
    gNum +=1
 +
    vs.SysBeep()
 +
 +
# no init!
 +
for gIndex in range(0, 10):
 +
    Increment()
 +
    # increments the variable gNum
 +
    # but only inside Increment!
 +
   
 +
vs.AlrtDialog(str(gNum))
 +
# rises error
 +
</code>
  
For example:
+
Error Message: NameError: global name 'gNum' is not defined
  
 +
|- style="vertical-align: top;"
 +
| '''FOR statements'''
 +
| '''Runs including last value:'''
 +
<code lang="pas">
 +
{ runs 3 times! 1, 2 and 3 }
 +
FOR i := 1 TO 3 DO
 +
    AlrtDialog(Concat(i));
 +
</code>
 +
| '''Runs excluding last value:'''
 
<code lang="py">
 
<code lang="py">
import vs;
+
# runs 2 times! 1 and 2
cnt = 0 # explicit is better than implicit :)
+
for i in range(1, 3):
 +
    vs.AlrtDialog(str(i))
 +
</code>
  
def DoSomething(h):
+
|- style="vertical-align: top;"
    # ... do something
+
| '''Colors'''
    cnt += 1 # variable should be incremented
+
|
 +
* Color Index:
 +
*: <code>SetPenFore(h, RGBToColorIndex(65535, 0, 0));</code>
 +
*: <code>PenFore(RGBToColorIndex(65535, 0, 0));</code>
 +
* RGB:
 +
*: <code>SetPenFore(h, 65535, 0, 0);</code>
 +
|
 +
* Color Index:
 +
*: <code>vs.SetPenFore(h, vs.RGBToColorIndex(65535, 0, 0)) </code>
 +
* RGB in Tuple:
 +
*: <code>vs.SetPenFore(h, (65535, 0, 0)) </code>
 +
* Hex in Tuple:
 +
*: <code>vs.SetPenFore(h, (0xFFFF, 0, 0))</code>
  
vs.ForEachObject(DoSomething, '(ALL)')  # pick objects by criteria, there the variable cnt will increment
+
Warning: don't forget the brakets:
vs.AlrtDialog(vs.Concat('Did something ', cnt, ' times.'))
+
* <code>vs.PenFore((65535, 0, 0)) </code> correct
 +
* <code>vs.PenFore(65535, 0, 0) </code> fails
 +
Error Message: - none! be careful! -
 +
 
 +
|- style="vertical-align: top;"
 +
| '''Concatenate text'''
 +
| '''Supports implicit conversion:'''
 +
: Both [[VS:Concat| Concat]] and [[VS:Message| Message]] support multiple variable types and convert them into string.
 +
* <code>t := Concat(10, ' fingers'); { OK }</code>
 +
* <code>Message(10, ' fingers'); { OK }</code>
 +
* <code>AlrtDialog(Concat(10, ' fingers')); { OK }</code>
 +
| '''Doesn't support implicit conversion:'''
 +
: For example an integer won't automatically be converted into string. Wrap it in [[VS:Concat| vs.Concat]] or [[VS:Message| vs.Message]], alternatively perform the needed conversion.
 +
* <code>t = 10 + ' fingers' # error</code>
 +
* <code>t = vs.Concat(10, ' fingers') # OK</code>
 +
* <code>vs.Message(10, ' fingers') # OK</code>
 +
* <code>vs.AlrtDialog(str(10) + ' fingers') # OK</code>
 +
* <code>vs.AlrtDialog(10 + ' fingers') # error </code>
 +
 
 +
Error Message: TypeError: unsupported operand type(s) for +: 'int' and 'str'
 +
 
 +
|- style="vertical-align: top;"
 +
| '''Encryption'''
 +
| Whatever .vs or .px file is linked through your includes, will be encrypted upon running the encrypt command. More infos [[VS:Include_Files_and_Encryption| here]].
 +
| Create list of your included files in an xml file. Please read [https://techboard.vectorworks.net/ubbthreads.php?ubb=showflat&Number=197639&Searchpage=1&Main=39809&Words=python&Search=true#Post197639 Vlado on Techboard]
 +
 
 +
|- style="vertical-align: top;"
 +
| '''Python version'''
 +
|
 +
| <code>import sys
 +
ver = sys.version_info</br>
 +
vs.Message(repr(ver))</br>
 
</code>
 
</code>
  
Error: UnboundLocalError: local variable can't be referenced before assignment
+
|- style="vertical-align: top;"
 +
| '''"import vs"'''
 +
|
 +
| <code>import vs</code> # do I need this?
  
But it doesn't work from within '''DoSomething''' and I can't turn DoSomething into a function outputting an integer, otherwise it won't fit the required callback syntax expected by [[VS:ForEachObject| ForEachObject]]
+
|- style="vertical-align: top;"
 +
'''Caching'''
 +
: some caching prevents your script to reflect changes:
 +
|
 +
| varPersistentPythonEngine = 412 { Boolean }
 +
In the SDK starting from VW 2014 we can read:
 +
''When True the Python engine is the same for the execution of all scripts, this solves some issues with Py_Initialize and Py_Finalize. For example, when debugging externally python leaves threas that cause crash if Py_Initialize and Py_Finalize is used for each script call. So, this allows the engine to be preserved between calls, however Vectorworks will delete all custom modules and objects defined in the engine prior each execution.''
 +
|}
  
Searching the web I found out that I am not alone in this misery. See [http://www.reddit.com/r/Python/comments/wbs1o/best_way_to_increment_of_1_in_python this], LOL. This comment wins, on my opinion: "We can make Python ask Perl to ask C."
+
== Lists ==
  
Now I'll try this mysterious approach treating the variable as a list (http://bytes.com/topic/python/answers/46419-how-does-one-write-function-increments-number source):
+
Lists are powerful in Python, below some fascinating lists manipulations. They remind me of Applescript:
 
<code lang="py">
 
<code lang="py">
def incr(counters): counters[0] += 1
+
months = "Jan Feb Mar Apr May Jun Jul"
 
+
months = months.split() # no splitter defined and it will use the empty space --> ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul']
counters =[100]
+
months[2] # --> 'Mar' note that the index is 0-based
incr(counters)
+
months2 = "Jan, Feb, Mar, Apr, May, Jun, Jul"
print counters [101]
+
months2.split(', ') # --> ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'] use comma and empty space as splitter
 +
months.append('Jul') # --> ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'] append adds an item to a list
 +
months.pop() #- -> 'Jul' pop fetches the last item of a list
 +
', sunny '.join(months) # --> ', sunny Jan, sunny Feb, sunny Mar, sunny Apr, sunny May, sunny Jun, sunny Sep'
 +
'-'.join(months[1:3]) # --> 'Feb-Mar'
 +
del months[2] # --> ['Jan', 'Feb', 'Apr', 'May', 'Jun', 'Jul']
 +
months = {1: 'Jan', 2: 'Feb', 3: 'Mar'} # --> {1: 'Jan', 2: 'Feb', 3: 'Mar'}
 
</code>
 
</code>
  
== Python caching ==
+
== Errors ==
 +
Python Error Messages: https://docs.python.org/3/library/exceptions.html
  
From the SDK, introduced by VW 2014:
+
BaseExceptions:
  varPersistentPythonEngine = 412 { Boolean }
+
  +-- SystemExit
''When True the Python engine is the same for the execution of all scripts, this solves some issues with Py_Initialize and Py_Finalize. For example, when debugging externally python leaves threas that cause crash if Py_Initialize and Py_Finalize is used for each script call. So, this allows the engine to be preserved between calls, however Vectorworks will delete all custom modules and objects defined in the engine prior each execution.''
+
+-- KeyboardInterrupt
 +
+-- GeneratorExit
 +
+-- Exception
 +
      +-- StopIteration
 +
      +-- ArithmeticError
 +
      |    +-- FloatingPointError
 +
      |    +-- OverflowError
 +
      |    +-- ZeroDivisionError
 +
      +-- AssertionError
 +
      +-- AttributeError
 +
      +-- BufferError
 +
      +-- EOFError
 +
      +-- ImportError
 +
      +-- LookupError
 +
      |    +-- IndexError
 +
      |    +-- KeyError
 +
      +-- MemoryError
 +
      +-- NameError
 +
      |    +-- UnboundLocalError
 +
      +-- OSError
 +
      |    +-- BlockingIOError
 +
      |    +-- ChildProcessError
 +
      |    +-- ConnectionError
 +
      |    |    +-- BrokenPipeError
 +
      |    |    +-- ConnectionAbortedError
 +
      |    |    +-- ConnectionRefusedError
 +
      |    |    +-- ConnectionResetError
 +
      |    +-- FileExistsError
 +
      |    +-- FileNotFoundError
 +
      |    +-- InterruptedError
 +
      |    +-- IsADirectoryError
 +
      |    +-- NotADirectoryError
 +
      |    +-- PermissionError
 +
      |    +-- ProcessLookupError
 +
      |    +-- TimeoutError
 +
      +-- ReferenceError
 +
      +-- RuntimeError
 +
      |    +-- NotImplementedError
 +
      +-- SyntaxError
 +
      |    +-- IndentationError
 +
      |        +-- TabError
 +
      +-- SystemError
 +
      +-- TypeError
 +
      +-- ValueError
 +
      |    +-- UnicodeError
 +
      |        +-- UnicodeDecodeError
 +
      |        +-- UnicodeEncodeError
 +
      |        +-- UnicodeTranslateError
 +
      +-- Warning
 +
          +-- DeprecationWarning
 +
          +-- PendingDeprecationWarning
 +
          +-- RuntimeWarning
 +
          +-- SyntaxWarning
 +
          +-- UserWarning
 +
          +-- FutureWarning
 +
          +-- ImportWarning
 +
          +-- UnicodeWarning
 +
          +-- BytesWarning
 +
          +-- ResourceWarning

Latest revision as of 22:00, 19 February 2020

Ciao,

I am Orso, an Italian Vectorscripter since many years. Some of you might know me from Vectorlab or the comments on the present Developer wiki. I feel very comfortable with Vectorscript but will now switch over to Python for even more power. I will try to share here comments, problems -and solutions- from the point of view of a non-programmer. --Orso.b.schmid (talk) 08:13, 17 May 2015 (EDT)

If you add comments, please use the full wiki formatting, easily available clicking on Advanced while on edit mode and don't forget to sign up your comment using --~~~~!

Vectorlab Archives

Here is the List Browsers article from the now dead Vectorlab site:

I stored some of the Vectorlab sites:

VS <> Py Rosetta Stone

Description Vectorscript Python
Statement ending: Semicolon always needed
  • AlrtDialog('test 1')
    AlrtDialog('test 2') { error }
  • AlrtDialog('test 1'); AlrtDialog('test 2'); { OK }
  • AlrtDialog('test 1') AlrtDialog('test 2') { error }
Semicolon needed only for multiple statements on one line:
  • vs.AlrtDialog('test 1')
    vs.AlrtDialog('test 2') # OK
  • vs.AlrtDialog('test 1'); vs.AlrtDialog('test 2') # OK
  • vs.AlrtDialog('test 1') vs.AlrtDialog('test 2') # error
Error Message: SyntaxError: invalid syntax
Case sensitivity Not case sensitive:
  • AlrtDialog('test'); { OK }
  • alrtDialog('test'); { OK }
  • alrtdialog('test'); { OK }
  • ALRTDIALOG('test'); { OK }
Case sensitive:
  • vs.AlrtDialog('test') # OK
  • vs.alrtDialog('test') # error
  • vs.alrtdialog('test') # error
  • vs.ALRTDIALOG('test') # error
Error Message: AttributeError: 'module' object has no attribute 'vs.ALRTDIALOG'
Empty brakes for functions
don't forget in python the empty brakets for routines without parameters, this rises errors that are so tricky to find.
Can be without brakets
  • FSActLayer; { no paramters: brakets not needed }
  • MySubroutine;
Can't be without brakets
  • vs.FSActLayer()
  • MySubroutine()
Error Message: - none! be careful! -
Empty handles
do pay attention also to the variable scope (see below).
  • h <> NIL
  • h != None
  • h != vs.Handle() # not inited instance of a handle, how cryptic
Variable scope
perhaps the largest source of error for the vectorscripter transitioning to python

Global wins over local:

  • Variables must be declared
  • Subroutines "see" their own variables and those of any parent function/procedure where they are contained.
{ GLOBAL ACCESS }
{ parent of subroutine "Increment" }
PROCEDURE Main;
    VAR
        { good praxis: label globals with "g" }
        gIndex, gNum : INTEGER; 
    
    { subroutine }
    PROCEDURE Increment;
        BEGIN
            { gNum is not defined in this subroutine 
            the parser climbs up parent containers
            until it finds a declaration for the var gNum.
            In this case it can be found in Main }
            gNum := gNum +1;
            SysBeep;
        END;
        
BEGIN
    gNum := 10; { init }
    FOR gIndex := 1 TO 10 DO
        Increment; { increments the variable gNum }
        
    AlrtDialog(Concat(gNum));
{ returns 20 }
END;
RUN(Main);

Local wins over global:

  • Variables must NOT be declared
  • Subroutines create automatically a local instance of any used variable.
# LOCAL ACCESS
# subroutine
def Increment():
    # gNum is not defined in this subroutine
    # the parser creates a local instance of the var gNum!
    gNum +=1
    vs.SysBeep
 
gNum = 10 # init
for gIndex in range(1, 10):
    Increment 
    # increments the variable gNum
    # but only inside Increment!
    
vs.AlrtDialog(str(gNum))
# returns 10! The global var didn't set
# GLOBAL ACCESS: CORRECT
# subroutine
def Increment():
    # gNum is not defined in this subroutine
    # tell the parser that you want to edit gNum global!
    global gNum
    gNum +=1
    vs.SysBeep()
 
gNum = 10 # init
# please observe that the range is NOT 1, 10!
for gIndex in range(0, 10):
    Increment()
    # increments the variable gNum
    # but only inside Increment!
    
vs.AlrtDialog(str(gNum))
# returns 20
# GLOBAL ACCESS: WRONG
# subroutine
def Increment():
    # gNum is not defined in this subroutine
    # tell the parser that you want to edit gNum global!
    global gNum
    gNum +=1
    vs.SysBeep()
 
# no init!
for gIndex in range(0, 10):
    Increment()
    # increments the variable gNum
    # but only inside Increment!
    
vs.AlrtDialog(str(gNum))
# rises error
Error Message: NameError: global name 'gNum' is not defined
FOR statements Runs including last value:
{ runs 3 times! 1, 2 and 3 }
FOR i := 1 TO 3 DO
    AlrtDialog(Concat(i));
Runs excluding last value:
# runs 2 times! 1 and 2
for i in range(1, 3):
    vs.AlrtDialog(str(i))
Colors
  • Color Index:
    SetPenFore(h, RGBToColorIndex(65535, 0, 0));
    PenFore(RGBToColorIndex(65535, 0, 0));
  • RGB:
    SetPenFore(h, 65535, 0, 0);
  • Color Index:
    vs.SetPenFore(h, vs.RGBToColorIndex(65535, 0, 0))
  • RGB in Tuple:
    vs.SetPenFore(h, (65535, 0, 0))
  • Hex in Tuple:
    vs.SetPenFore(h, (0xFFFF, 0, 0))

Warning: don't forget the brakets:

  • vs.PenFore((65535, 0, 0)) correct
  • vs.PenFore(65535, 0, 0) fails
Error Message: - none! be careful! -
Concatenate text Supports implicit conversion:
Both Concat and Message support multiple variable types and convert them into string.
  • t := Concat(10, ' fingers'); { OK }
  • Message(10, ' fingers'); { OK }
  • AlrtDialog(Concat(10, ' fingers')); { OK }
Doesn't support implicit conversion:
For example an integer won't automatically be converted into string. Wrap it in vs.Concat or vs.Message, alternatively perform the needed conversion.
  • t = 10 + ' fingers' # error
  • t = vs.Concat(10, ' fingers') # OK
  • vs.Message(10, ' fingers') # OK
  • vs.AlrtDialog(str(10) + ' fingers') # OK
  • vs.AlrtDialog(10 + ' fingers') # error
Error Message: TypeError: unsupported operand type(s) for +: 'int' and 'str'
Encryption Whatever .vs or .px file is linked through your includes, will be encrypted upon running the encrypt command. More infos here. Create list of your included files in an xml file. Please read Vlado on Techboard
Python version import sys

ver = sys.version_info
vs.Message(repr(ver))

"import vs" import vs # do I need this?
Caching
some caching prevents your script to reflect changes:
varPersistentPythonEngine = 412 { Boolean }

In the SDK starting from VW 2014 we can read: When True the Python engine is the same for the execution of all scripts, this solves some issues with Py_Initialize and Py_Finalize. For example, when debugging externally python leaves threas that cause crash if Py_Initialize and Py_Finalize is used for each script call. So, this allows the engine to be preserved between calls, however Vectorworks will delete all custom modules and objects defined in the engine prior each execution.

Lists

Lists are powerful in Python, below some fascinating lists manipulations. They remind me of Applescript:

months = "Jan Feb Mar Apr May Jun Jul"
months = months.split() # no splitter defined and it will use the empty space --> ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul']
months[2] # --> 'Mar' note that the index is 0-based
months2 = "Jan, Feb, Mar, Apr, May, Jun, Jul"
months2.split(', ') # --> ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'] use comma and empty space as splitter 
months.append('Jul') # --> ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'] append adds an item to a list 
months.pop() #- -> 'Jul' pop fetches the last item of a list
', sunny '.join(months) # --> ', sunny Jan, sunny Feb, sunny Mar, sunny Apr, sunny May, sunny Jun, sunny Sep'
'-'.join(months[1:3]) # --> 'Feb-Mar'
del months[2] # --> ['Jan', 'Feb', 'Apr', 'May', 'Jun', 'Jul']
months = {1: 'Jan', 2: 'Feb', 3: 'Mar'} # --> {1: 'Jan', 2: 'Feb', 3: 'Mar'}

Errors

Python Error Messages: https://docs.python.org/3/library/exceptions.html

BaseExceptions:

+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
     +-- StopIteration
     +-- ArithmeticError
     |    +-- FloatingPointError
     |    +-- OverflowError
     |    +-- ZeroDivisionError
     +-- AssertionError
     +-- AttributeError
     +-- BufferError
     +-- EOFError
     +-- ImportError
     +-- LookupError
     |    +-- IndexError
     |    +-- KeyError
     +-- MemoryError
     +-- NameError
     |    +-- UnboundLocalError
     +-- OSError
     |    +-- BlockingIOError
     |    +-- ChildProcessError
     |    +-- ConnectionError
     |    |    +-- BrokenPipeError
     |    |    +-- ConnectionAbortedError
     |    |    +-- ConnectionRefusedError
     |    |    +-- ConnectionResetError
     |    +-- FileExistsError
     |    +-- FileNotFoundError
     |    +-- InterruptedError
     |    +-- IsADirectoryError
     |    +-- NotADirectoryError
     |    +-- PermissionError
     |    +-- ProcessLookupError
     |    +-- TimeoutError
     +-- ReferenceError
     +-- RuntimeError
     |    +-- NotImplementedError
     +-- SyntaxError
     |    +-- IndentationError
     |         +-- TabError
     +-- SystemError
     +-- TypeError
     +-- ValueError
     |    +-- UnicodeError
     |         +-- UnicodeDecodeError
     |         +-- UnicodeEncodeError
     |         +-- UnicodeTranslateError
     +-- Warning
          +-- DeprecationWarning
          +-- PendingDeprecationWarning
          +-- RuntimeWarning
          +-- SyntaxWarning
          +-- UserWarning
          +-- FutureWarning
          +-- ImportWarning
          +-- UnicodeWarning
          +-- BytesWarning
          +-- ResourceWarning
Personal tools
NamespacesFFFF

Variants
Actions
Advanced Search
See Also
Navigation
Toolbox