Python for the Rocket MultiValue Developer – Part 2 of 3 – Getting Started with the u2py module

In part one of the series “Python for the Rocket MultiValue Developer – Part 1 of 3 – Introduction” we discussed the architecture of the Python / MultiValue solution including the fact that the MultiValue and Python code both run in the same process.

In this section, you’ll learn how Python interacts with the MultiValue Application Platform, through the use of the u2py module.

The u2py Module

The u2py module for Python allows developers to interact with the MultiValue Application Platform in the following ways:

  • run U2 ECL/TCL commands **
  • read/write U2 files **
  • handle U2 dynamic arrays
  • manage U2 SELECT lists
  • call U2BASIC catalogued subroutines
  • control U2 transactions

** Introduced in this article

Getting Started with the u2py module

The installation of Rocket UniData and Rocket UniVerse includes Python (version 3.4.1).  The initial install of Python sets up the needed “.pth” file to point to the u2py module.  The u2py.py module provides the interaction from Python to the MultiValue Application Platform.

>>> import u2py

While there are no issues with launching your Python program from any directory, the directory will need to be in a MultiValue account to allow access to the database.

Prior to using the u2py objects and methods, you must insure that there is a VOC file.

The VOC (vocabulary) file serves as the central repository for information about MultiValue accounts.

It contains direct information such as commands, paragraphs, and keywords you can use, as well as pointers to menus, data and dictionary files, and cataloged programs. Each time a user starts a UniData session, the first file UniData reads is the VOC file for that account. Each account’s VOC file serves as the entry point for the command processor. Each UniData account must contain a VOC file and its dictionary, D_VOC.

run MultiValue ECL/TCL commands

ECL (Environment Control Language) and TCL (Terminal Control Language)  for UniData and UniVerse respectively are the interactive command processors used by the MultiValue Application Platforms.

u2py.Command is the simplest of the u2py Python objects to use.  It takes the text of the MultiValue command you wish to execute, and provides a method to run it.

If you are not in a directory that is set up for MultiValue, and/or you do not have privileges to the VOC file, you will get an error when using the u2py module.

                   >>> import u2py
                   >>> u2py.Command("WHO").run()
                   Error msgno = 427. args = VOC
                   errno=2: No such file or directory

When you can access a VOC file in the current working directory, you will be able to work with the MultiValue Application Platform.
                   >>> import u2py
                   >>> u2py.Command("WHO").run()
                   mrajkowski          Console     10:49:01 Dec 16 2016
                   >>>

Note that it is also possible to start a Python session from the MultiValue TCL/ECL prompt.  Since you are already in the database, there is no need to worry about the existence and accessibility of the VOC file.

We will delve into accessing Python from the MultiValue TCL/ECL commands in  “Python for the Rocket MultiValue Developer – Part 3 of 3 – Leveraging the Power of Python”

One feature of the u2py.Command.run method that needs to be pointed out is how it handles standard out.

If the method is executed as in the previous example, the output is displayed in standard out, and if you assigned what is returned to the method to a variable, you would see that nothing is returned.

                  python> a = u2py.Command("WHO").run()
                  2 UV From ROCKET1\mrajkowski
                  python> a
                  python> type(a)
                  <class 'NoneType'>
                  python>

While this is useful to launch commands, there are times the developer would want to capture the output.
                  python> a = u2py.Command("WHO").run(capture=True)
                  python> a
                  '2 UV From ROCKET1\\mrajkowski\n'
                  python> type(a)
                  <class 'str'>

As you can see the output is directed to the variable, and not displayed in the standard output.  At this time, that is the extent of the u2py.Command object. If the run method produces an error nothing is returned or raised.
                  python> a = u2py.Command("not-a-valid-command").run()
                  Verb "NOT.A.VALID.COMMAND" is not in your VOC.
                  python> a = u2py.Command("not-a-valid-command").run(capture=True)
                  python> a
                  'Verb "NOT.A.VALID.COMMAND" is not in your VOC.\n'

While there is no easy way to determine if an error occurred with the MultiValue command, there is a simple workaround with the use of the u2py.Subroutine Object. Stay tuned for a future article that will provide more detail.

File Access

For this getting started session, I will briefly cover what is essential to the u2py module. Since there are multiple remaining u2py Objects, I decided to describe how to read and write items in the MultiValue Application Platform.  This is done in the u2pyFile object.

Opening a MultiValue file

So, there are three ways to open the data portion of a MultiValue file in Python.

Default type of file is Data:

                  python> test1 = u2py.File("VOC")
                  python> test1
                  <u2py.File name='VOC' status='opened'>

Use the DATA_FILE data element from the u2py module.
                  python> test2 = u2py.File("VOC", u2py.DATA_FILE)
                  python> test2
                  <u2py.File name='VOC' status='opened'>

Or use the integer representation of the DATA_FILE data element.
                 python> test3 = u2py.File("VOC", 0)
                 python> test3
                 <u2py.File name='VOC' status='opened'>

Similarly, there are two options for opening a dictionary file.

Use the DICT_FILE data element from the u2py module.

                 python> test2 = u2py.File("VOC", u2py.DICT_FILE)
                 python> test2
                 <u2py.File name='DICT VOC' status='opened'>

Or use the integer representation of the DICT_FILE data element.
                 python> test3 = u2py.File("VOC", 1)
                 python> test3
                 <u2py.File name='DICT VOC' status='opened'>

Since the u2py.File Object can raise an exception, you should program for it.
i.e.
                 python> try:
                 ...    notAFileInTheVoc = u2py.File("no_a_real_file_name")
                 ... except u2py.U2Error:
                 ...    print("problem opening the file")
                 ...
                 problem opening the file

We will cover dealing with exceptions and more advanced I/O topics in future posts.

Reading and Writing an Item from a MultiValue File

Now that we have a u2py.File Object, there are three methods that read data from the MultiValue file.

  • read                                  —  read a record in the file
  • readv                                —  read the specified field of a record in the file
  • readnamedfields            —  read the specified fields by name of a record in the file

For brevity we will review just the read method at this time. I will go into the other methods, and when to use them in a future post.

                 python> file = u2py.File("CUSTOMER")
                 python> record = file.read(2)
                 python> record
                 <u2py.DynArray value=b'Partner, Bonnie\xfe19th & Elm\xfeLakewood\xfeCO\xfe80443\xfe3034495641\xfeB914\
                 xfdB2297\xfe9498\xfd9500\xfeC\xfe19'>

Note that the read method will raise an exception if there is an error, as in the case of a missing item.
                 python> record = file.read("not_a_item")
                 Traceback (most recent call last):
                 File "<console>", line 1, in <module>
                 File "C:\U2\ud82\bin\u2py.py", line 99, in read
                 return DynArray(super().read(*args))
                 u2py.U2Error: (30001) Record not found

The read method returns a dynamic array, which we will discuss in future posts. In this discussion, we will cover a helpful function on the u2py.DynaArray object “to_list()”
                 python> as_a_list = record.to_list()
                 python> as_a_list
                 ['Partner, Bonnie', '19th & Elm', 'Lakewood', 'CO', '80443', '3034495641', ['B914', 'B2297'], ['9498','9500'], 'C', '19']

Conversely, the write function will write a dynamic array to an item in the MultiValue file.
                 python> file.write(9999, u2py.DynArray(as_a_list))

While we did not go into all the objects, methods and functions of the u2py module, I hope I provided you with enough information to peak your curiosity.  In the third part of this series we will explore how to leverage Python from the MultiValue command prompt and BASIC Python API.

Michael Rajkowski

Michael Rajkowski 8 Posts

As a member of the Rocket MultiValue Support organization, Michael has worked with MultiValue for over 25 years in numerous professional roles. He is especially fascinated with the areas of MultiValue that intersect with other technologies. He recently moved to Irvine, where he can not only expand his MultiValue expertise to include the Rocket D3 product family, but also where he, his wife and son can enjoy being closer to Disneyland.

2 Comments

  • Avatar

    Moe Reply

    September 4, 2019 at 9:45 pm

    Hi,
    Would you be able to help with an example of reading multiple attributes in a single readnamedfields call?

    • Michael Rajkowski

      Michael Rajkowski Reply

      September 9, 2019 at 1:50 pm

      Moe,

      Here is a simple example.

      1. Start Python.
      :PYTHON

      2. Import u2py
      python> import u2py

      3. Create you u2py.File object
      python> file = u2py.File(“MEMBERS”)

      4. Create a list of which fields you want to get
      python> fields = [ “FIRST_NAME”, “LAST_NAME”, “CITY”, “STATE_CODE”, “ZIP” ]

      5. Call the readnamedfields method
      python> rec = file.readnamedfields(“0110”, u2py.DynArray(fields))
      python> rec

      6. I like to look at the returned data as a list. The list will be the same order as the field list you sent into the method.

      python> rec_list = rec.to_list()
      python> rec_list
      [‘Anita’, ‘Johnson’, ‘New Glasgow’, ‘NE’, ‘01870’]
      python> fields
      [‘FIRST_NAME’, ‘LAST_NAME’, ‘CITY’, ‘STATE_CODE’, ‘ZIP’]
      python>

      Mike Rajkowski

Leave a Comment

Your email address will not be published. Required fields are marked *