1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

How do I access variable file in a script?

Discussion in 'Alibre Script' started by R-man, Jun 30, 2019.

  1. R-man

    R-man Senior Member

    My script sets values for over a hundred variables that are shared in the creation of several parts. Right now I have everything in one script. I set the values of the variables in a section at the top, then several sections to create the various parts. As I include more parts (and more variables) the script is getting unmanageable. My plan is to break it into many scripts, one for each part.

    In this case I will need to have each script access the same set of variables. I have been experimenting with importing 'sub-scripts' into a main script. I can run code from another file, but it seems I can't have variables recognized. For example, MyName = "Doug" when executed in the sub-script does not give MyName a value in the main script, or vice versa.

    I guess I'm trying to create my own method of having global variables, within the context of scripting. My hope was that I could import a sub-script and it would simply execute exactly as if it were part of the main script, but so far no success. Can anyone advise on how I might achieve my goal? Can I use the built-in system of global variables to do this?
  2. NateLiqGrav

    NateLiqGrav Alibre Super User

  3. idslk

    idslk Alibre Super User

    Hello R-man,

    are they all in a formt like:
    There are many ways to store information in files in python.
    Eg. CSV, Excel, Text ...
    There is also a way to use user data in AlibreScript.
    The solution depends a little bit on what you have to store and restore...
  4. R-man

    R-man Senior Member

    Hi Stefan,

    I can understand how I can store values (4.56 let's say) in an Excel file, but what will make "print DiaGD" give the result "4.56"? It seems that I'd still need 100+ assignment statements in each script. The Excel method does have the benefit of assuring that the value is only updated in one place but I also want to only have to have the assignment of the value in one place.
  5. idslk

    idslk Alibre Super User

    Hello R-man,

    as an example here on row of an .CSV-File:
    a cutout (there's a bit more of preperation needed...) of a script code:
      with open(Verzeichnis + Standardsfile, 'rb') as f:
        reader = csv.reader(f)
        for row in reader:
          print row
          Value1 = row[0]
          Value2 = row[1]
          DiaGD = row[2]
          Test = row[3]
          MyDoug = row[4]
          Z_Turn = row[5]
    results the same like:
          Value1 = 200.0
          Value2 = 250.0
          DiaGD = 300.0
          Test = 15.0
          MyDoug = 20.0
          Z_Turn = 15.0
    So if you place a copy of the csv reading and assigning, yes, in each of your scripts you have to maintain only the CSV-file or...
    (The reading of an excel-file is nearly the same...)
    Of course there are more sophisticated methods, like reading the Name and the Value of the variable...

  6. R-man

    R-man Senior Member

    Thanks Stefan,

    After thinking about how to use excel I came up with a similar idea. I combined it with what I've recently learned about python 'global' declarations.

    Python does have a 'global' declaration but the declarations are separate from the assignment. With all my parameters, and new ones being added I thought it would be too much headache to keep track of the variable names in two places. But I now realize I can automate all of that by having a script read the excel and create a python file with all the declarations and assignments. That has to be imported into my scripts to access the variables.

    If it turns out well, or not, I'll post the results.
  7. NateLiqGrav

    NateLiqGrav Alibre Super User

    Last edited: Jul 6, 2019
  8. ajayre

    ajayre Alibre Super User

    Define all of your variables in a dictionary:

    MyGlobals = {
      'MyName': 'Doug',
      'DiaGD': 4.56
    then pass this dictionary to each function you call, whether it is in the current script or it is in another script.

    Result = CreatePart(MyGlobals)
    See the link Nate gave for how to import a script into another script and make it's functions available.

    More info on dictionaries here: https://docs.python.org/2.7/tutorial/datastructures.html#dictionaries

  9. R-man

    R-man Senior Member

    Assuming I have a parameter AvHeight and a library 'LIB' it seems I'd have to use replace AvHeight with LIB('AvHeight'). Is there anyway of regaining the ability to use AvHeight directly? To have every variable accessed in this way would make my code more of a jumble than it is already.

    I see you've really put a lot of work into that system, but I am not inclined to try it because even a small hiccup would defeat me, since couldn't (or wouldn't want to) figure out what went wrong.
    Last edited: Jul 5, 2019
  10. ajayre

    ajayre Alibre Super User

    I'm not sure what you are referring to, sorry. Can you post an example? Andy
  11. albie0803

    albie0803 Alibre Super User

    Unless I'm missing something, simply AvHeight = LIB('AvHeight') is all you need once and then you can use AvHeight through the rest of your script.
  12. R-man

    R-man Senior Member


    Yes, that would allow me to keep my code as is - thanks. However, I am developing the scripts as I develop my design, so I'm adding parameters all the time, and most of them affect several parts. (It's probably not how most folks use scripting, but once my script is perfected the parts are perfected and the script's life is over unless some part of the design needs changing.)

    So a library would give me the ability to only update a value in one location, and as you point out I could keep my code as is, but I still would need to update a long list of assignment statements in many scripts every time I introduced a new parameter (several per hour). Not much benefit over just copying the parameter script into each part script (something I could automate I guess). Nate's system of "external saved variables" looks like it was motivated by the same vision of 'global' variables for scripts as I have. (Nate: Correct me if I'm wrong!)

    This example, and others here, have added to my python education and helped me simplify and better organize my scripts, so thanks to all.

    As it stands now I have one main script that initiates all of the parameters, and has most of the code in functions. The driving part selectively calls the functions to update parts as required. It's not so bad a system - I just thought putting each separate task into a separate script would be a sounder approach.
  13. idslk

    idslk Alibre Super User

    Hello R-man,

    can you post a little sample script?
    What are you using the scripts for?

  14. NateLiqGrav

    NateLiqGrav Alibre Super User

    Correct. And I really like my solution because variables can be created on the fly.
    I have started a separate post about my Settings class: https://www.alibreforum.com/forum/i...s-release-load-save-external-variables.21047/
  15. R-man

    R-man Senior Member

    Great! I will follow closely.

    In the meantime I've figured out how to import my variables and reference them relatively conveniently.
    ( MyGlobalVariables has assignments var1 = 33 and var2 = 22.)

    import sys
    # make sure my globals folder is in sys.path (but only one time)
    p = "C:\\Users\\dh\Documents\\RotoAlibre\\Alibre\\TestPackage"
    if p not in sys.path:
      sys.path.insert(0, p)
    # import the global variables using short alias "g" and reload to get latest version
    import MyGlobalVariables as g
    # code
    print g.var1, g.var2, g.var1 + g.var2
  16. R-man

    R-man Senior Member

    Thanks to everyone who took an interest and contributed ideas and clues. Finally I have 'Hack2' ready, and this really is a hack in the sense that it uses the python system in a way that is not as intended.

    This works by adding variables to the namespace used for python reserved names. However the changes are temporary and disappear when the Alibre 'console' is closed. Also, before a variable is set it is verified to not be in the namespace. It's not complicated but it took a long time to get working properly. It works well for my needs, but I'm presenting it here FYI only. If anyone is interested in trying this, the three scripts below should be a good start. Just update the folder and file names to suit.

    The parameter file: TestParams.py
    # This is a small section of the parameter assignments taken directly from my parameters script
        # origin
        HmX = 5.0 # 0.0  #  shift from actual origin
        HmY = 5.0 # 0.0
        HmZ = 5.0 # 0.0
        # concentric axles
        AxCtX    =  HmX
        AxCtY    =  HmY
        Ax3Od    =  4.00
        Ax3Hx    =  6.35   # with corners rounded to  7.00 (alternate method if using slide cam)
        Ax3Sq    =  3.175  # .125" corners rounded to 4.00 (standard method if no slide cam)
        Ax2Id    =  4.00
        Ax2Od    =  7.00
        Ax2Hx    =  6.35   # with corners rounded to  7.00
        Ax1Id    =  7.00
        Ax1Od    = 10.00
        Ax1Hx    =  9.00   # with corners rounded to 10.00
        # axle bearings
        Ax3BrId  =  4.00
        Ax3BrOd  =  7.00
        Ax3BrTh  =  2.50  # maybe 3.00 ????????????????
        Ax1BrId  = 10.00
        Ax1BrOd  = 15.00
        Ax1BrTh  =  3.00
        # wheel parameters
        WhTh   =   6.00
        WhSp   =   5.50
        WhDm   =  30.00
        WhRd   =  WhDm/2
        Wh1CtZ =  HmZ + Ax1BrTh + WhTh/2
        Wh2CtZ =  Wh1CtZ  + WhSp
        Wh3CtZ =  Wh2CtZ  + WhSp
    The script that processes the parameter file: InitParams.py
    import __builtin__ as bi
    # If not yet created, create list of names that have been added
    if "MyParamNames" not in vars(bi):
      bi.MyParamNames = []          
    path = "C:\\Users\\dh\Documents\\RotoAlibre\\Alibre\\Hack2"
    f = open(path + "\\" + "TestParams.py", "r")             # use full path to params file
    for x in f:
      x = x.split('#')[0].strip()                          # keep text before first '#'
      if not len(x) == 0 and not x[0] == '#' and "=" in x: # make sure len>0, no '#', and has '='
        name  = x.split('=')[0].strip()                    # split at '=' into name & value
        value = x.split('=')[1].strip()                    #     and strip away white space
        if name not in vars(bi) or name in MyParamNames:   # name is OK
          if name not in MyParamNames:
            MyParamNames.append(name)                      # add name to list
          exec("bi." + name + " = " + value)               # inialize name with value
          print "Name is invalid"                          # name was not OK
    And here is a TestScript that imports InitParams:

    # All the regular imports etc go here
    # Add file path to sys.path (but only once) to make sure import works
    p = "C:\\Users\\dh\Documents\\RotoAlibre\\Alibre\\Hack2"
    if p not in sys.path:
      sys.path.insert(0, p)
    # Initalize Parameters
    import InitParams
    # Put code here
    # test to see how things went
    print "HmX =     " + str(HmX)
    print "HmY =     " + str(HmY)
    print "HmZ =     " + str(HmZ)
    print "AxCtX =   " + str(AxCtX)
    print "AxCtY =   " + str(AxCtY)
    print "Ax3Od =   " + str(Ax3Od)
    print "Ax3Hx =   " + str(Ax3Hx)
    print "Ax3Sq =   " + str(Ax3Sq)
    print "Ax2Id =   " + str(Ax2Id)
    print "Ax2Od =   " + str(Ax2Od)
    print "Ax2Hx =   " + str(Ax2Hx)
    print "Ax1Id =   " + str(Ax1Id)
    print "Ax1Od =   " + str(Ax1Od)
    print "Ax1Hx =   " + str(Ax1Hx)
    print "Ax3BrId = " + str(Ax3BrId)
    print "Ax3BrOd = " + str(Ax3BrOd)
    print "Ax3BrTh = " + str(Ax3BrTh)
    print "Ax1BrId = " + str(Ax1BrId)
    print "Ax1BrOd = " + str(Ax1BrOd)
    print "Ax1BrTh = " + str(Ax1BrTh)
    print "WhTh =    " + str(WhTh)
    print "WhSp =    " + str(WhSp)
    print "WhDm =    " + str(WhDm)
    print "WhRd =    " + str(WhRd)
    print "Wh1CtZ  = " + str(Wh1CtZ)
    print "Wh2CtZ  = " + str(Wh2CtZ)
    print "Wh3CtZ  = " + str(Wh3CtZ)
    # print out the names that were used (for no particular reason)
    print  MyParamNames
    One last comment: any variables created within the script, and any re-assignment to variables, will NOT be recorded back to the TestParams.py file. However, it only takes seconds to add a new parameter and re-run InitParams so that it can be used.
  17. Lew_Merrick

    Lew_Merrick Alibre Super User

    R-man -- Have you looked at the "CSV Import" system? It allows you t create a "CommaSeparatedValue" input file that can be "decoded" to loaded Screipt-base variables. I have not done this in a while (i.e.more than a year) so the context and format do not leap to what's left of my mind -- but it is an approach that I regularly find useful...
  18. idslk

    idslk Alibre Super User

    Hello Lew,
    have you taken a look at post #5 ?
    ajayre likes this.
  19. R-man

    R-man Senior Member

    Lew: I have jumped to a conclusions about how CSV files would be used and admit that I have not looked carefully into what has been done regarding a "CSV Import" system. I will though. Thanks.

    Stefan: The same applies to post #5 which I looked at, but not as carefully as I might have. In light of my recent discoveries I now attach a lot more significance to the remark: "Of course there are more sophisticated methods, like reading the Name and the Value of the variable...". Thanks.

    So stand by as I apply my recently gained knowledge to developing a method (perhaps unsophisticated) inspired by that comment! For anyone who is following my attempts I'll call it 'Hack3'.
    Last edited: Jul 10, 2019
  20. idslk

    idslk Alibre Super User

    Hello R-man,

    i'm looking for your next hack;)
    If you do run the following code in Python37 it works as expexted...
    Also if you run it multiple times.
    import sys
    for loop in range(3):
        for i in range(len(sys.path)):
            print (loop,i,sys.path[i])
        print (' ',)
        p = "C:\\Users\\Default\\Documents"
        if p not in sys.path:
          sys.path.insert(0, p)
    If you do the same in AlibreScript it behaves a little bit different...
    import sys
    for loop in range(3):
        for i in range(len(sys.path)):
            print loop,i,sys.path[i]
        print ' ',
        p = "C:\\Users\\Default\\Documents"
        if p not in sys.path:
          sys.path.insert(0, p)
    the printed sys.path gets longer and longer.
    I do not have any explanation for this, do you have one?


Share This Page