Calling Python from CLLE with parameters

Any IBM i topic that does not fit in another forum
Post Reply
versa005
Posts: 2
Joined: Wed Apr 24, 2024 7:16 pm

Calling Python from CLLE with parameters

Post by versa005 »

Hi Scott

Thanks a lot for everything you do for the IBMi community.

Here is my question: I have a Python program that takes two parameters: 1) IFS path and 2) Output_data. I pass these parameters from a CLLE program using QSH. The Python program populates the output_data with a list of all files and folders in the IFS path and ideally should return it to the calling CLLE.

I tested the Python program, and it is working correctly. However, the sys.argv[2], which contains the output_data from my Python program, is not getting populated in my CLLE program. My outputdata in CL program is always blanks. Can you please help me with this?"


My CL program:

Code: Select all

PGM                                                                  
DCL        VAR(&NULL) TYPE(*CHAR) LEN(1) VALUE(X'00')                
DCL        VAR(&QSHCMD) TYPE(*CHAR) LEN(2000)                        
DCL        VAR(&ROOTPATH) TYPE(*CHAR) LEN(100) +                     
             VALUE('/home/ibm_python')                               
DCL        VAR(&OUTPUTDATA) TYPE(*CHAR) LEN(256)                     
DCL        VAR(&OUTPUTCNT) TYPE(*INT) VALUE(0)                       
                                                                     
CHGVAR     VAR(&OUTPUTDATA) VALUE(&OUTPUTDATA *TCAT +                
             &NULL)                                                  
                                                                     
CHGVAR     VAR(&QSHCMD) +                                            
             VALUE('/QOpensys/pkgs/bin/python3 +                     
             /lansrv/ibm_python/dev/deployifsobj/getifsi+            
             nfo.py ' *BCAT &ROOTPATH *BCAT &OUTPUTDATA)             
                                                                     
QSH        CMD(&QSHCMD)                                              
                                                                     
ENDPGM                                                               

My Python program

Code: Select all

import os
import sys
# Retrieve parameters from command line
root_path = sys.argv[1]
output_data = sys.argv[2]

def get_next_level_items(root_path):
    items = []
    for item in os.listdir(root_path):
        full_path = os.path.join(root_path, item)
        if os.path.isdir(full_path):
            items.append((item, 'directory')) 
        elif os.path.isfile(full_path):
            items.append((item, 'file'))
    items.sort(key=lambda x: (x[1], x[0]))
    return [item[0] for item in items]

# Example usage
next_level_items = get_next_level_items(root_path)
output_data = next_level_items
sys.argv[2] = output_data
print("Sys.argv[2] : ", sys.argv[2])
Scott Klement
Site Admin
Posts: 661
Joined: Sun Jul 04, 2021 5:12 am

Re: Calling Python from CLLE with parameters

Post by Scott Klement »

Unix programs are not meant to be able to send output through their parameters. (Though, the way you're doing it wouldn't work even for a native IBM i program where output can be returned via parameters... but since Unix programs can't return output via parameters, fixing that wouldn't help.)

Instead, send the output another way.

Suggestions:
  • Write the output to stdout. If you must use the clunky CL QSH command, you can redirect it's output to a file and read the file in your program.
  • Or use STDOUT and use a better tool to call it, such as UNIXCMD, popen, or the OPNPIPE, RCVPIPE, etc commands.
  • Or make it a REST API and call it that way -- this is more work, but the most versatile and best performing option.
Having said all of that, are you creating an overly complex monstrosity just to use Python? Why not read the list of files from the folder directly in CL or in another language like RPG?
Scott Klement
Site Admin
Posts: 661
Joined: Sun Jul 04, 2021 5:12 am

Re: Calling Python from CLLE with parameters

Post by Scott Klement »

If you like the idea of using UNIXCMD, there's a presentation with examples here:
https://www.scottklement.com/presentations/#UNIXCMD

If you liked the idea of reading the IFS directly with RPG, there's an example of one method here (albeit, this is a very old example)
https://www.scottklement.com/rpg/ifs_eb ... addir.html

There are at least a few dozen ways to tackle the problem of reading IFS filenames... I don't want to build an exhastive list here, especially when what you asked was how to get output from Python. I'm just really puzzled as to why you wanted to use Python for something like this where it just makes the job 10x more complicated.
versa005
Posts: 2
Joined: Wed Apr 24, 2024 7:16 pm

Re: Calling Python from CLLE with parameters

Post by versa005 »

Thank you, Scott, for your quick response.

Let me explain the purpose of my program. We are currently developing several Python programs on our IBMi system, stored in our IFS directory on our development server. I'm currently working on a process to deploy these Python objects to our production server. Unfortunately, we don't have GitHub on our system.

My task involves creating a screen that displays the contents of the directories /home/mypython/dir1, /home/mypython/dir2, and /home/mypython/dir3, allowing users to select the Python program or directory they want to install on the production server.

Initially, I thought it would be straightforward to retrieve the directory structure using Python and display it in a subfile. However, as Python won't work for this purpose, I'll follow your suggestion of reading the IFS content in RPG and displaying it on the screen.

Thanks again for your assistance.
Scott Klement
Site Admin
Posts: 661
Joined: Sun Jul 04, 2021 5:12 am

Re: Calling Python from CLLE with parameters

Post by Scott Klement »

Python WILL work.. it's just more complicated than other solutions. I'm just not understanding why you'd want to use it for this.

If there's actually some stuff going on that makes Python a better choice because you're using some python modules you installed via pip, or you are using a large valuable python routine you wrote or found somewhere, then absolutely use python.

But if all it does is list files, so what? That's a REALLY simple thing to do, so why create the necessary plumbing to get the data copied from a Python program to a CL program?
Post Reply