### The SIC command PYTHON

If Python and the NumPy module was detected, SIC provides the command PYTHON with various behaviors depending on what follows (or not) on command line:

- Starting Python: in all cases, the first call to the command starts the Python interpreter in the background if it was not already launched. This is done only once:

      SIC> PYTHON
      Python 2.5 (r25:51908, Nov 14 2006, 22:44:28)
      [GCC 4.1.1 20061011 (Red Hat 4.1.1-30)] on linux2
      Entering interactive session. Type 'Sic()' to go back to SIC.
      >>>

  The SIC variables are not yet available at this stage, assuming the user may not need them. You have to invoke the .get() method (with no arguments) to import them (see section for details):

      >>> pysic.get()
      Importing all SIC variables into Python...
      ... done.
      >>>

- Switching to Python: by default, if no argument follows, an interactive session is launched (see above). It has the same behavior as the standard interactive Python mode: multiline definition for functions and classes, and command history. To exit both SIC and Python, type CTRL-D as usual. The exit() function is also available. To go back to SIC, call the Sic object with Sic().

- Executing a Python script: if the first argument which follows the command PYTHON is a string ending with the three characters `.py', SIC assumes that you gave it a Python filename. SIC will look in all the MACRO#DIR: directories it usually looks in for its own procedures. SIC also solves the logical names if any. If the file is found, it will be executed by the Python interpreter in the current name space:

      SIC> TYPE test.py
      print "Hello world!"
      a = 1
      a
      print "a value is", a

      # This line is a comment
      for i in xrange(1,4):
         print i

      if True:
         print "True"
      else:
         print "False"

      SIC> PYTHON test.py
      Hello world!
      a value is 1
      1
      2
      3
      True
      SIC>

  Note that the command a = 1 does not print any output. You have to explicitely request a print to see any value. After the execution you fall back to the SIC prompt. If the SIC%VERIFY flag is set to ON, commands are printed before execution:

      SIC> SIC VERIFY ON
      I-SIC,  VERIFY       is ON
      SIC> PYTHON test.py
      >>> print "Hello world!"
      Hello world!
      >>> a = 1
      >>> a
      >>> print "a value is", a
      a value is 1
      >>> for i in xrange(1,4):
      ...    print i
      1
      2
      3
      >>> if True:
      ...    print "True"
      ... else:
      ...    print "False"
      True
      SIC>

- Passing arguments to Python scripts: You can pass arguments to the Python script after its name. They will be available in the sys.argv list as usually when you launch Python scripts from shell:

      SIC> TYPE test2.py
      import sys
      for i in sys.argv:
        print i, type(i)
      SIC> PYTHON test2.py 1 qwerty "ABCD"
      test2.py <type 'str'>
      1 <type 'str'>
      qwerty <type 'str'>
      "ABCD" <type 'str'>
      SIC>

  Arguments are also parsed by SIC before being sent to Python:

      SIC> DEFINE DOUBLE A
      SIC> LET A 1.234
      SIC> py test2.py A "A" 'A'
      test2.py <type 'str'>
      A <type 'str'>
      "A" <type 'str'>
      1.234 <type 'str'>
      SIC>

- Parsing Python script arguments: Sic does NOT interpret arguments starting by a slash as options of the command. This can be useful to simulate a Sic-like calling sequence, but implemented in Python. The Gildas-Python module sicparse.py can help you to parse such options in Python:

      SIC> type test3.py
      import sicparse
      parser = sicparse.OptionParser()

      # Declare 1 known option:
      parser.add_option(
        "-m",           # Short name
        "--myopt",      # Full name
        dest="optval",  # Variable name where option value will be stored
        nargs=1,        # Number of arguments expected
        type="float",   # Kind of arguments
        default=1.23)   # Default value if option is absent

      # Call again add_options to declare more options

      # Parse:
      try:
        (options, args) = parser.parse_args()
      except:
        raise StandardError,"Invalid option"

      print "Success"
      print "Command arguments: ",args
      print "Options: ",options

      SIC> python test3.py ABCD
      Success
      Command arguments:  ['ABCD']
      Options:  {'optval': 1.23}
      SIC> python test3.py ABCD /myopt 4.56
      Success
      Command arguments:  ['ABCD']
      Options:  {'optval': 4.56}
      SIC>

  But of course, as in Sic, arguments starting with a slash must be then double-quoted:

      SIC> python test3.py /home/me
      Usage: test3.py [options]

      test3.py: error: no such option: /home/me
      Traceback (most recent call last):
        File "./test3.py", line 19, in <module>
          raise StandardError,"Invalid option"
      StandardError: Invalid option
      SIC> python test3.py "/home/me"
      Success
      Command arguments:  ['"/home/me"']
      Options:  {'optval': 1.23}

- Raising errors in Python scripts: There are typically 3 ways to raise errors in Python scripts:
  1. let Python raise its own errors, e.g.

         SIC> type test4.py
         print 1/0
         SIC> python test4.py
         Traceback (most recent call last):
           File "./test4.py", line 1, in <module>
             print 1/0
         ZeroDivisionError: integer division or modulo by zero
         SIC>

  2. raise your own Python error, e.g.

         SIC> type test5.py
         arg = 0
         if (arg==0):
           raise StandardError, "Argument must not be null"
         else:
           print 1/arg
         SIC> python test5.py
         Traceback (most recent call last):
           File "./test5.py", line 3, in <module>
             raise StandardError, "Argument must not be null"
         StandardError: Argument must not be null
         SIC>

  3. turn ON the error status of the SICPYTHON command, such as it behaves correctly when hand is given back to Sic. For example:

         SIC> type test6.py
         def main():
           try:
             print 1/0
           except:
             print "E-SIC, Some error when printing 1/0"
             pysic.sicerror()  # Set the SIC\PYTHON command error
             return            # Leave the function and the script

         if __name__ == "__main__":
             main()

         SIC> py test6.py
         E-SIC, Some error when printing 1/0
         SIC>

     Note that these 3 methods raise an error in Sic, i.e. the flag SIC%ERROR is true on return, and that procedures will stop in such a case (if ON ERROR is PAUSE).

     The last syntax gives the best integration in Sic, because in particular it hides the Python error traceback. However, this requires 1) to catch the error with a try/except clause, 2) to tell Sic an occured thanks to the method sicerror(), and 3) to leave the script right after. This last point can only be achieved by putting the whole code in a (top) function, from which you can return when required. exit is not satisfying because it performs too much cleaning, nor raise since a traceback would be back.

- Sending Sic-formatted messages to Sic: the method message() can be used to send messages to Sic. They will be formatted and filtered by the standard Sic messaging mechanism, e.g.:

      >>> pysic.message(pysic.seve.i,"FOO","Hello world!")
      I-FOO,  Hello world!

  The seve instance contains the usual elements (f, e, w, r, i, d, t, c) which have to be used to indicate the message severity.

- Executing a single-line Python command: if any other character string follows the PYTHON command, it will be sent to the Python interpreter as a single line command. Multiline feature can not be used in this case:

      SIC> PYTHON print "Hello world!"
      Hello world!
      SIC>

  The command line sent after the PYTHON command is executed by the Python interpreter. It is also printed after a »> prompt if the SIC%VERIFY flag is ON:

      SIC> SIC VERIFY ON
      I-SIC,  VERIFY       is ON
      SIC> PYTHON print "Hello world!"
      >>> print "Hello world!"
      Hello world!
      SIC>

  Take care that what you type at SIC prompt after PYTHON command is now case sensitive! There will be no reformatting, except for single-quoted strings:

      SIC> PYTHON print 'Hello world?'
      >>> print 'Helloworld?'
      Helloworld?
      SIC>

  Please use double-quotes instead for commands sent by SIC to Python.