Package: qlik-sdk
Qlik SDKQlik's Python SDK allows you to leverage the APIs of Qlik Cloud platform from the comfort of python.qlik-sdk-pythonInstallGetting startedAuthentication optionsAPI keysChangelogContributingBugsFeaturesDevelopingExamplesapps_items.pyflask_oauth.pyimport_export.pyrpc basics example_custom_type.pyrpc basics lists app_object_list app_object_list.pyrpc basics lists field_list field_list.pyrpc basics lists variable_list variable_list.pyrpc data hypercubes pivot hypercube_pivot.pyrpc data hypercubes stacked hypercube_stacked.pyrpc data hypercubes straight hypercube_straight.pyrpc rpc.pyInstallpython3-mpipinstall--upgradeqlik-sdkGetting startedThe lowest supported python version is3.8.
A good place to start is ourexamples. Take a look and learn how to authorize and use our REST and RPC clients to access the APIs. If you're in a real hurry, the essence of our examples is shown below.fromqlik_sdkimportAuth,AuthType,Configapi_key="<MY_API_KEY>"base_url="<URL_TO_MY_TENANT>"# E.g. https://foo.qlikcloud.eu.comq=Qlik(config=Config(host=base_url,auth_type=AuthType.APIKey,api_key=api_key))user=q.users.get_me()print("Logged in as: "+user.name)# For REST calls: auth.rest# For RPC calls: auth.rpcAuthentication optionsAPI keysAn API key is a token representing a user in your tenant. Anyone may interact with the platform programmatically using the API key. The token contains the user context, respecting the access control privileges the user has in your tenant. More info can be found onQlik Dev Portal.For a step-by-step guide on how to get an API key for your tenant, check thistutorial.OAuth2OAuth is a standard security protocol for authorization and delegation. It allows third party applications to access API resources without disclosing the end-user credentials.For a step-by-step guide on how to create an OAuth client for your tenant, checkCreating and managing OAuth clients# Authorization# Create auth objectconfig=Config(host='my-tenant.qlikcloud.com',auth_type=AuthType.OAuth2,client_id='<clientId>',client_secret='<clientSecret>',redirect_url='<redirectUrl>',scope='<scopes>',)auth=Auth(config=config)# for login redirect to authorization uri for OAuth exchange token flow# which will call callback endpoint with credentialsredirect(auth.generate_authorization_url(),code=301)# on callback endpoint (redirectUri), exachange the creadentials with tokenauth.authorize(request.full_path)# fetch a resourceuser=auth.rest(path="/users/me")# refreshing tokenauth.refresh_token()# deauthorizationauth.deauthorize()Examplesapps_items.pyimportosimportuuidfromdataclassesimportasdictfromdotenvimportdotenv_valuesfromqlik_sdkimport(AppAttributes,AppUpdateAttributes,AuthType,Config,CreateApp,Qlik,UpdateApp,)# get QCS_SERVER and QCS_API_KEY from .env file in the same folder as this scriptfile_dir=os.path.dirname(os.path.abspath(__file__))dotenv_path=os.path.join(file_dir,".env")ifnotos.path.exists(dotenv_path):print("Missing .env file: "+dotenv_path)env_values=dotenv_values(dotenv_path=dotenv_path)host=env_values.get("QCS_SERVER",False)api_key=env_values.get("QCS_API_KEY",False)config=Config(host=host,auth_type=AuthType.APIKey,api_key=api_key)q=Qlik(config=config)user=q.users.get_me()print("Logged in as: "+user.name)deflog_req(req):print("request:",req.method,req.url)returnreqdeflog_res(res):print("response:",res.request.method,res.request.url,"->",res.status_code)returnresq.apps.auth.rest.interceptors["response"].use(log_res)q.apps.auth.rest.interceptors["request"].use(log_req)# The body parameter can be either an object or a dict# The recommended way is to use an object# create apps - 2 methods - dict body or obj body# create app - dict bodyrandom_app_name1=str(uuid.uuid1())app_dict_body=q.apps.create(data={"attributes":{"name":random_app_name1}})app_dict_body.delete()# create app - obj bodyrandom_app_name2=str(uuid.uuid1())app=q.apps.create(data=CreateApp(attributes=AppAttributes(name=random_app_name2,description="desc",spaceId="")),)# Convert app object to dictapp_asdict=asdict(app)# set load script, reload and evaluate expressionwithapp.open():script="Load RecNo() as N autogenerate(200);"app.set_script(script)app.do_reload()eval=app.evaluate("SUM([N])")print(eval)# Set attribute# body: dictapp.set(data={"attributes":{"name":"set-name-dict"}})# body: objupdate_name=str(uuid.uuid1())app.set(UpdateApp(attributes=AppUpdateAttributes(description="new description",name=update_name)))# items list - query param nameitems0=q.items.get_items(name=update_name)app.delete()items1=q.items.get_items(name=update_name)# get_items using an app name query param, result-length before and after deleteprint(f"found items matching:{update_name}, before and after delete:{len(items0)},{len(items1)}")items=q.items.get_items()first_100_item_names=[]foriteminitems.pagination:iflen(first_100_item_names)<100:first_100_item_names.append(item.name)else:breakflask_oauth.pyimportosimportrandomfromdotenvimportdotenv_valuesfromflaskimportFlask,redirect,render_template,request# src. should be removed when example is publicfromsrc.qlik_sdkimportAuth,AuthType,Config# get QCS_SERVER and QCS_API_KEY from .env file in the same folder as this scriptfile_dir=os.path.dirname(os.path.abspath(__file__))dotenv_path=os.path.join(file_dir,".env")ifnotos.path.exists(dotenv_path):print("Missing .env file: "+dotenv_path)env_values=dotenv_values(dotenv_path=dotenv_path)host=env_values.get("QCS_SERVER_OAUTH",False)client_id=env_values.get("CLIENT_ID_WEB",False)client_secret=env_values.get("CLIENT_SECRET_WEB",False)redirect_url="http://localhost:3000/login/callback"config=Config(host=host,auth_type=AuthType.OAuth2,client_id=client_id,client_secret=client_secret,redirect_url=redirect_url,scope=["offline_access"],)auth=Auth(config=config)app=Flask(__name__)template_data={"is_logged_in":False,"user":"","eval_result":""}@app.route("/")defindex():try:user=auth.rest(path="/users/me")user=user.json()template_data["is_logged_in"]=Truetemplate_data["user"]=f"User:{user['name']}is logged in"exceptException:template_data["is_logged_in"]=Falsetemplate_data["user"]=""returnrender_template("index.html",template_data=template_data)@app.route("/login")deflogin():returnredirect(auth.generate_authorization_url(),code=301)@app.route("/login/callback")defcallback():auth.authorize(request.full_path)returnredirect("/",code=301)@app.route("/logout")deflogout():auth.deauthorize()template_data["is_logged_in"]=Falsetemplate_data["user"]=""returnredirect("/",code=301)@app.route("/refresh")defrefresh():auth.refresh_token()returnredirect("/",code=301)@app.route("/websocket")defwebsocket():random_id=random.randint(1,1000)app_id=f"SessionApp_{random_id}"try:# Open a websocket for a session app using RpcClientrpc_session=auth.rpc(app_id)try:rpc_session.open()app_handle=(rpc_session.send("GetActiveDoc",-1))["qReturn"]["qHandle"]rpc_session.send("SetScript",app_handle,"Load RecNo() as N autogenerate(10)",)rpc_session.send("DoReload",app_handle)eval_result=rpc_session.send("Evaluate",app_handle,"SUM([N])")template_data["is_logged_in"]=Truetemplate_data["eval_result"]=eval_result["qReturn"]exceptExceptionaserr:print(f"rpc_session error occured:{err}")returnredirect("/",code=500)finally:rpc_session.close()print("rpc_connection closed")exceptExceptionaserr:print(f"error occured while setting up auth:{err}")returnredirect("/",code=500)returnredirect("/",code=301)if__name__=="__main__":app.run(host="localhost",port=3000,debug=True)import_export.pyimportjsonimportosimportshutilimportuuidfromdotenvimportdotenv_valuesfromqlik_sdkimportAuthType,Config,Qlik# get QCS_SERVER and QCS_API_KEY from .env file in the same folder as this scriptfile_dir=os.path.dirname(os.path.abspath(__file__))dotenv_path=os.path.join(file_dir,".env")ifnotos.path.exists(dotenv_path):print("Missing .env file: "+dotenv_path)env_values=dotenv_values(dotenv_path=dotenv_path)host=env_values.get("QCS_SERVER",False)api_key=env_values.get("QCS_API_KEY",False)withopen(os.path.join(file_dir,"sheetListDef.json"))asjson_file:sheet_list_def=json.load(json_file)config=Config(host=host,auth_type=AuthType.APIKey,api_key=api_key)q=Qlik(config=config)# Print user nameuser=q.users.get_me()print("Logged in as: "+user.name)# Create a managed spacespace_name="publish-apps-sdk-test"+str(uuid.uuid1())shared_space=q.spaces.create({"name":space_name,"description":"space used for testing","type":"managed",})print(f"created space with name{space_name}and id{shared_space.id}")# Import app - (app with multiple sheets)qvf_file=os.path.join(file_dir,"two-sheets.qvf")app_name="import-test"+str(uuid.uuid1())withopen(qvf_file,"rb")asqvf_data:imported_app=q.apps.import_app(data=qvf_data,name=app_name)print(f"imported app with name{app_name}and id{imported_app.attributes.id}")# Publish each sheetprint(f"open app with id{imported_app.attributes.id}and publish all sheets")withimported_app.open():session_obj=imported_app.create_session_object(sheet_list_def)sheet_list_layout=session_obj.get_layout()sheet_id_list=[q.qInfo.qIdforqinsheet_list_layout.qAppObjectList.qItems]forsheet_idinsheet_id_list:print(f"publishing sheet with id{sheet_id}")sheet_obj=imported_app.get_object(sheet_id)sheet_obj.publish()# Publish the appprint(f"publish app with id{imported_app.attributes.id}to space with id{shared_space.id}")published_app=imported_app.publish({"spaceId":shared_space.id})print(f"published app id{published_app.attributes.id}")# export applocal_filename=f"exported{uuid.uuid1()}.qvf"temp_contents_url=imported_app.export()# download app streaming to filewithq.auth.rest(path=temp_contents_url,method="get",stream=True)asr:withopen(local_filename,"wb")asf:shutil.copyfileobj(r.raw,f)print(f"Exported{published_app.attributes.name}to{local_filename}")ext_file_path=env_values.get("EXTENSION_ZIP_PATH",False)# Upload extensionwithopen(ext_file_path,"rb")asext_file:ext=q.extensions.create(file=ext_file)# TODO# set properties - change sheet name# upload theme# apply themes on the app# import datafiles# Delete everything createdprint("cleaning up")ext.delete()imported_app.delete()published_app.delete()shared_space.delete()os.remove(local_filename)rpc basics example_custom_type.pyimportosimportsysimportuuidfromdotenvimportdotenv_valuesfromqlik_sdkimportApps,Auth,AuthType,Config# get QCS_SERVER and QCS_API_KEY from .env file in the same folder as this scriptfile_dir=os.path.dirname(os.path.abspath(__file__))dotenv_path=os.path.join(file_dir,"../../.env")ifnotos.path.exists(dotenv_path):print("Missing .env file: "+dotenv_path)env_values=dotenv_values(dotenv_path=dotenv_path)host=env_values.get("QCS_SERVER",False)api_key=env_values.get("QCS_API_KEY",False)config=Config(host=host,auth_type=AuthType.APIKey,api_key=api_key)auth=Auth(config)apps=Apps(config)session_app_id="SessionApp_"+str(uuid.uuid1())session_app=apps.create_session_app(session_app_id)withsession_app.open():# create a generic object of a custom typeproperties={"qInfo":{"qType":"custom-object"},}obj=session_app.create_session_object(properties)# set a custom property i.e. a property not defined in GenericObjectPropertiesproperties["CustomProperty"]="custom-property-value"obj.set_properties(properties)# fetch the properties and validate that the custom property is returnednew_props=obj.get_properties()ifnew_props.qInfo.qType!="custom-object":sys.exit(1)ifnew_props.CustomProperty!="custom-property-value":sys.exit(1)rpc basics lists app_object_list app_object_list.pyimportosimportsysimportuuidfromdotenvimportdotenv_valuesfromsrc.qlik_sdkimportApps,AuthType,Config,GenericObjectPropertiesfromsrc.qlik_sdk.apis.AppsimportJsonObjectfromsrc.qlik_sdk.apis.QiximportAppObjectListDef,NxInfoclassCustomObjectProperties(GenericObjectProperties):meta:dict[str,str]=Nonedeflist_app_objects():# get QCS_SERVER and QCS_API_KEY from .env file in the same folder as this scriptfile_dir=os.path.abspath("")dotenv_path=os.path.join(file_dir+"/examples",".env")ifnotos.path.exists(dotenv_path):print("Missing .env file: "+dotenv_path)env_values=dotenv_values(dotenv_path=dotenv_path)host=env_values.get("QCS_SERVER",False)api_key=env_values.get("QCS_API_KEY",False)config=Config(host=host,auth_type=AuthType.APIKey,api_key=api_key)apps=Apps(config)session_app_id="SessionApp_"+str(uuid.uuid1())session_app=apps.create_session_app(session_app_id)withsession_app.open():foriinrange(10):properties=CustomObjectProperties(qInfo=NxInfo(qType="my-object"),meta=dict({"title":f"my-object-{i}"}),)session_app.create_object(properties)list_properties=GenericObjectProperties(qInfo=NxInfo(qType="my-list"),qAppObjectListDef=AppObjectListDef(qType="my-object",qData=JsonObject(title="/meta/title")),)try:object=session_app.create_object(qProp=list_properties)layout=object.get_layout()returnlayout.qAppObjectList.qItems.__len__()exceptValueErrorase:print(e.__class__)iflist_app_objects()!=10:print("Error in number of objects .....")sys.exit(1)rpc basics lists field_list field_list.pyimportosimportsysimportuuidfromdotenvimportdotenv_valuesfromsrc.qlik_sdkimportApps,AuthType,Config,GenericObjectPropertiesfromsrc.qlik_sdk.apis.QiximportFieldListDef,NxInfoscript="""TempTable:LoadRecNo() as Field1,Rand() as Field2,Rand() as Field3AutoGenerate 100"""# get QCS_SERVER and QCS_API_KEY from .env file in the same folder as this scriptfile_dir=os.path.abspath("")dotenv_path=os.path.join(file_dir+"/examples",".env")ifnotos.path.exists(dotenv_path):print("Missing .env file: "+dotenv_path)env_values=dotenv_values(dotenv_path=dotenv_path)host=env_values.get("QCS_SERVER",False)api_key=env_values.get("QCS_API_KEY",False)config=Config(host=host,auth_type=AuthType.APIKey,api_key=api_key)apps=Apps(config)session_app_id="SessionApp_"+str(uuid.uuid1())session_app=apps.create_session_app(session_app_id)withsession_app.open():# Load in some data into the session document:session_app.set_script(script)session_app.do_reload()# Create a field list using qFieldListDef and list all fields available in the document.object=session_app.create_session_object(GenericObjectProperties(qInfo=NxInfo(qType="my-field-list"),qFieldListDef=FieldListDef(),))layout=object.get_layout()print("field-list ",layout.qFieldList.qItems)items=layout.qFieldList.qItemsif(items.__len__()!=3oritems[0].qName!="Field1"oritems[1].qName!="Field2"oritems[2].qName!="Field3"):print("Error generated qFieldsLists ......")sys.exit(1)rpc basics lists variable_list variable_list.pyimportosimportsysimportuuidfromdotenvimportdotenv_valuesfromsrc.qlik_sdkimportApps,AuthType,Config,GenericObjectPropertiesfromsrc.qlik_sdk.apis.AppsimportJsonObjectfromsrc.qlik_sdk.apis.QiximportNxInfo,VariableListDefscript="""TempTable:LoadRecNo() as Field1,Rand() as Field2,Rand() as Field3AutoGenerate 100"""# get QCS_SERVER and QCS_API_KEY from .env file in the same folder as this scriptfile_dir=os.path.abspath("")dotenv_path=os.path.join(file_dir+"/examples",".env")ifnotos.path.exists(dotenv_path):print("Missing .env file: "+dotenv_path)env_values=dotenv_values(dotenv_path=dotenv_path)host=env_values.get("QCS_SERVER",False)api_key=env_values.get("QCS_API_KEY",False)config=Config(host=host,auth_type=AuthType.APIKey,api_key=api_key)apps=Apps(config)session_app_id="SessionApp_"+str(uuid.uuid1())session_app=apps.create_session_app(session_app_id)withsession_app.open():# Load in some data into the session document:session_app.set_script(script)session_app.do_reload()session_app.create_variable_ex(GenericObjectProperties(qInfo=NxInfo(qType="variable"),qComment="sample comment",qDefinition="=Count(Field1)",qName="vVariableName",))variable=session_app.get_variable_by_id("vVariableName")object=session_app.create_session_object(GenericObjectProperties(qInfo=NxInfo(qType="VariableList"),qVariableListDef=VariableListDef(qType="variable",qData=JsonObject(tags="/tags"),qShowSession=True,qShowConfig=True,qShowReserved=True,),))layout=object.get_layout()layout.qVariableList.qItemsprint("variable-list: ",layout.qVariableList.qItems)foriteminlayout.qVariableList.qItems:ifitem.qName=="vVariableName":sys.exit(0)sys.exit(1)rpc data hypercubes pivot hypercube_pivot.pyimportosimportsysimportuuidfromdotenvimportdotenv_valuesfromsrc.qlik_sdkimportApps,AuthType,Configfromsrc.qlik_sdk.apis.Qiximport(GenericObjectProperties,HyperCubeDef,NxDimension,NxInfo,NxInlineDimensionDef,NxInlineMeasureDef,NxMeasure,NxPage,NxSelectionCell,)script="""TempTable:LoadRecNo() as ID,RecNo()+1 as ID2,Rand() as ValueAutoGenerate 100"""# get QCS_SERVER and QCS_API_KEY from .env filefile_dir=os.path.dirname(os.path.abspath(__file__))dotenv_path=os.path.join(file_dir,"../../../../.env")ifnotos.path.exists(dotenv_path):print("Missing .env file: "+dotenv_path)env_values=dotenv_values(dotenv_path=dotenv_path)host=env_values.get("QCS_SERVER",False)api_key=env_values.get("QCS_API_KEY",False)config=Config(host=host,auth_type=AuthType.APIKey,api_key=api_key)apps=Apps(config)session_app_id="SessionApp_"+str(uuid.uuid1())session_app=apps.create_session_app(session_app_id)withsession_app.open():# Load in some data into the session document:session_app.set_script(script)session_app.do_reload()obj=session_app.create_object(GenericObjectProperties(qInfo=NxInfo(qType="my-pivot-hypercube"),qHyperCubeDef=HyperCubeDef(qDimensions=[NxDimension(qDef=NxInlineDimensionDef(qFieldDefs=["ID"])),NxDimension(qDef=NxInlineDimensionDef(qFieldDefs=["ID2"])),],qMeasures=[NxMeasure(qDef=NxInlineMeasureDef(qDef="Sum(Value)",))],qMode="EQ_DATA_MODE_PIVOT",qAlwaysFullyExpanded=True,),))data=obj.get_hyper_cube_pivot_data("/qHyperCubeDef",[NxPage(qHeight=5,qLeft=0,qTop=0,qWidth=2,)],)print("HyperCude object data: ",data)obj.select_pivot_cells("/qHyperCubeDef",[NxSelectionCell(qType="D",qRow=1,qCol=0)],False,False)data=obj.get_hyper_cube_pivot_data("/qHyperCubeDef",[NxPage(qHeight=5,qLeft=0,qTop=0,qWidth=2,)],)print("Hypercube data pages after selection: ",data)ifnot(len(data)==1andlen(data[0].qData)==1andlen(data[0].qTop)==1anddata[0].qTop[0].qText=="Sum(Value)"):print("Error in generated stack pages ......")sys.exit(1)rpc data hypercubes stacked hypercube_stacked.pyimportosimportsysimportuuidfromdotenvimportdotenv_valuesfromsrc.qlik_sdkimportApps,AuthType,Configfromsrc.qlik_sdk.apis.Qiximport(GenericObjectProperties,HyperCubeDef,NxDimension,NxInfo,NxInlineDimensionDef,NxInlineMeasureDef,NxMeasure,NxPage,NxSelectionCell,)script="""TempTable:LoadRecNo() as ID,RecNo()+1 as ID2,Rand() as ValueAutoGenerate 100"""# get QCS_SERVER and QCS_API_KEY from .env filefile_dir=os.path.dirname(os.path.abspath(__file__))dotenv_path=os.path.join(file_dir,"../../../../.env")ifnotos.path.exists(dotenv_path):print("Missing .env file: "+dotenv_path)env_values=dotenv_values(dotenv_path=dotenv_path)host=env_values.get("QCS_SERVER",False)api_key=env_values.get("QCS_API_KEY",False)config=Config(host=host,auth_type=AuthType.APIKey,api_key=api_key)apps=Apps(config)session_app_id="SessionApp_"+str(uuid.uuid1())session_app=apps.create_session_app(session_app_id)withsession_app.open():# Load in some data into the session document:session_app.set_script(script)session_app.do_reload()obj=session_app.create_object(GenericObjectProperties(qInfo=NxInfo(qType="my-stacked-hypercube",),qHyperCubeDef=HyperCubeDef(qDimensions=[NxDimension(qDef=NxInlineDimensionDef(qFieldDefs=["ID"])),NxDimension(qDef=NxInlineDimensionDef(qFieldDefs=["ID2"])),],qMeasures=[NxMeasure(qDef=NxInlineMeasureDef(qDef="Sum(Value)",))],qMode="EQ_DATA_MODE_PIVOT_STACK",qAlwaysFullyExpanded=True,),))data=obj.get_hyper_cube_stack_data("/qHyperCubeDef",[NxPage(qHeight=5,qLeft=0,qTop=0,qWidth=2,)],10000,)print("HyperCude stack data: ",data)obj.select_pivot_cells("/qHyperCubeDef",[NxSelectionCell(qType="D",qRow=1,qCol=0,)],False,False,)data=obj.get_hyper_cube_stack_data("/qHyperCubeDef",[NxPage(qHeight=5,qLeft=0,qTop=0,qWidth=2,)],10000,)print("Hypercube stack data pages after selection: ",data)ifnot(len(data)==1andlen(data[0].qData)==1andlen(data[0].qData[0].qSubNodes)==1andlen(data[0].qData[0].qSubNodes[0].qSubNodes)==1):print("Error in generated stack pages ......")sys.exit(1)rpc data hypercubes straight hypercube_straight.pyimportosimportsysimportuuidfromdotenvimportdotenv_valuesfromsrc.qlik_sdkimportApps,AuthType,Configfromsrc.qlik_sdk.apis.Qiximport(GenericObjectProperties,HyperCubeDef,NxDimension,NxInfo,NxInlineDimensionDef,NxInlineMeasureDef,NxMeasure,NxPage,)script="""TempTable:LoadRecNo() as ID,Rand() as ValueAutoGenerate 100"""# get QCS_SERVER and QCS_API_KEY from .env filefile_dir=os.path.dirname(os.path.abspath(__file__))dotenv_path=os.path.join(file_dir,"../../../../.env")ifnotos.path.exists(dotenv_path):print("Missing .env file: "+dotenv_path)env_values=dotenv_values(dotenv_path=dotenv_path)host=env_values.get("QCS_SERVER",False)api_key=env_values.get("QCS_API_KEY",False)config=Config(host=host,auth_type=AuthType.APIKey,api_key=api_key)apps=Apps(config)session_app_id="SessionApp_"+str(uuid.uuid1())session_app=apps.create_session_app(session_app_id)withsession_app.open():# Load in some data into the session document:session_app.set_script(script)session_app.do_reload()obj=session_app.create_object(GenericObjectProperties(qInfo=NxInfo(qType="my-straight-hypercube",),qHyperCubeDef=HyperCubeDef(qDimensions=[NxDimension(qDef=NxInlineDimensionDef(qFieldDefs=["ID"]))],qMeasures=[NxMeasure(qDef=NxInlineMeasureDef(qDef="=Sum(Value)",))],qInitialDataFetch=[NxPage(qHeight=5,qWidth=2)],),))layout=obj.get_layout()print("Hypercube data pages: ",layout)data=obj.select_hyper_cube_cells("/qHyperCubeDef",[0,2,4],[0],False,False)print("After selection (notice the `qState` values)")print("HyperCude object data: ",data)layout=obj.get_layout()print(layout)ifnot(len(layout.qHyperCube.qDimensionInfo[0].qGroupFieldDefs)==1andlayout.qHyperCube.qDimensionInfo[0].qGroupFieldDefs[0]=="ID"andlayout.qInfo.qType=="my-straight-hypercube"):print("Error in generated layout ......")sys.exit(1)rpc rpc.pyimportosimportuuidfromdotenvimportdotenv_valuesfromqlik_sdkimportAuth,AuthType,Config,Qlikfromqlik_sdk.rpcimportRequestObject# get QCS_SERVER and QCS_API_KEY from .env file in the same folder as this scriptfile_dir=os.path.dirname(os.path.abspath(__file__))dotenv_path=os.path.join(file_dir,"../.env")ifnotos.path.exists(dotenv_path):print("Missing .env file: "+dotenv_path)env_values=dotenv_values(dotenv_path=dotenv_path)host=env_values.get("QCS_SERVER",False)api_key=env_values.get("QCS_API_KEY",False)auth=Auth(Config(host=host,auth_type=AuthType.APIKey,api_key=api_key))q=Qlik(Config(host=host,auth_type=AuthType.APIKey,api_key=api_key))deflog_request_interceptor(request:RequestObject)->RequestObject:print("request: "+str(request))returnrequestdeflog_qreturn_response_interceptor(response):if"result"inresponseand"qReturn"inresponse["result"]:qreturn=str(response["result"]["qReturn"])print(f"qReturn:{qreturn}")returnresponse# register interceptorsauth.rpc.interceptors["request"].use(log_request_interceptor)auth.rpc.interceptors["response"].use(log_qreturn_response_interceptor)session_app_id="SessionApp_"+str(uuid.uuid1())rpc_session=auth.rpc(app_id=session_app_id)withrpc_session.open()asrpc_client:app=rpc_client.send("OpenDoc",-1,session_app_id)handle=app["qReturn"]["qHandle"]script="Load RecNo() as N autogenerate(200);"# set load script and reloadrpc_client.send("SetScript",handle,script)rpc_client.send("DoReload",handle)# parameters can be passed without name which will be sent positional in an arraycount_expr="COUNT([N])"positional_eval=rpc_client.send("Evaluate",handle,count_expr)print(f"Evaluate{count_expr}={positional_eval}")# parameters can also be passed with name which will be sent as an objectsum_expr="SUM([N])"keyword_eval=rpc_client.send("Evaluate",handle,qExpression=sum_expr)print(f"Evaluate{sum_expr}={keyword_eval}")