Run Python Activity - Basic Example Needed
We have Workflow 5 set up on premise and the Application Pool being run as a local user on the server that has the ability to execute python on the server.
Can anyone provide the most basic example of how to use the 'Run Python Activity'. I realize this would involve a server workflow and client workflow to call the server workflow.
I would love to see an example set of workflows that takes the following basic python script, located at the path 'C\temp\basic.py'):
def my_result():
the_string = 'My output from python'
return (the_string)
my_result()
And displays an alert window with the result (i.e. 'My output from python'). I've tried a couple of different ways trying to follow the help documentation but can't seem to get it to work.
Any help would be much appreciated!
Matt
-
Matt,
I actually have a demo that is on my todo list to post a blog on when I get a few fires put out. But you should be able to piece together what we are doing.
This is a script to pull environment variables from a server and uses Python to return value requested. It comes in 3 pieces but does what you are after. Ask any questions and Zack or myself will try to respond.
Client Workflow (use "Open by URL" to copy)
https://www.arcgis.com/home/item.html?id=6520b63d0ebd40449ed805c2048470e4
Server Workflow (use "Open by URL" to copy)
https://www.arcgis.com/home/item.html?id=e4bfbfbf2ebe4b76815804345ae750cc
Python Script:
""" Title: Get OS Environment Variables Description: Quick script that takes a list of os environment variable keys and returns a JSON string of the key:value pairs. If a variable does not exist, "ERROR: OS Variable not found." is returned. Requires: Written in Python 3.7.3 but should work in all current versions of Python. :ORGANIZATION: geoWidgets by Digital Data Services, Inc. :CONTACT: https://www.geowidgets.io :UPDATED: 2019-06-24 """ from json import dumps from os import environ from sys import argv def main(env_variables): # Skip first argv, which is the script source keys = env_variables[1:] # Set keys that the server is allowed to return blacklisted_keys = [] # Blacklist has precedence over whitelist whitelisted_keys = ['TEMP', 'TMP', 'geowidgets_demo', 'USERNAME', 'password', 'windir'] """ Takes a list of keys and searches for then in the OS environment variables. Returns a JSON formatted string of keys and values. :param keys: String list of OS environment variables :return: JSON string of key:value pairs """ use_whitelist = len(whitelisted_keys) > 0 env_dict = {} for key in keys: if (key not in environ) or (key in blacklisted_keys) or (use_whitelist and key not in whitelisted_keys): # Withhold secret keys, provide same message for secrets and novalues to be sneaky env_dict[key] = 'ERROR: No OS variable "%s" found.' % key else: # Add environment to output dictionary env_dict[key] = environ[key] return dumps(env_dict) if __name__ == '__main__': main(env_variables)
We recommend storing the Python script in C:\ProgramData\Geocortex\Workflow\PythonScripts\getOSEnvirons.py and don't forget your permissions.
We hope to have this written up as a tutorial blog post sometime this month.
Best,
-Tom
0 -
Tom,
Thanks for the very quick response! Would you be able to export the server side workflow as a JSON file? When trying to copy from a URL, designer assumes that it is a client side workflow and strips out or replaces the server side tools (see screenshot) with client side tools (i.e. run workflow instead of run python). At least I think that is what is happening :)
Thanks again!
Matt
0 -
Guess that is good and bad. Here's the json formatted:
{ "components": [{ "steps": [{ "inputs": {}, "transitions": [{ "inputs": {}, "id": 5, "target": { "id": 6 }, "position": "90,60 90,140" } ], "id": 3, "purpose": "start", "title": "Start", "position": "0,0" }, { "inputs": { "pythonFile": "C:\\ProgramData\\Geocortex\\Workflow\\PythonScripts\\getOSEnvirons.py", "arguments": { "accessors": ["$inputs"], "annotations": [{ "kind": "idref", "index": 0, "count": 7 } ], "code": "$inputs.inputs.variableNames.join(' ')", "source": "$inputs.inputs.variableNames.join(' ')" } }, "transitions": [{ "inputs": {}, "id": 12, "target": { "id": 17 }, "position": "90,420 90,460", "sourceConnector": "bottom" } ], "id": 4, "action": "gcx:wf:server::RunPython", "description": "Run server script that returns dictionary of system environment variables", "position": "-30,290", "title": "Run Python Script", "name": "runPython" }, { "inputs": { "json": { "accessors": ["$runPython"], "annotations": [{ "kind": "idref", "index": 0, "count": 10 } ], "code": "$runPython.result", "source": "$runPython.result" } }, "transitions": [{ "inputs": {}, "id": 18, "target": { "id": 8 }, "position": "90,530 90,570", "sourceConnector": "bottom" } ], "id": 17, "action": "gcx:wf:core::ParseJson", "position": "-30,460", "title": "Parse JSON to Object", "name": "scriptOutput" }, { "inputs": { "name": "success", "value": { "accessors": ["$runPython"], "annotations": [{ "kind": "idref", "index": 1, "count": 10 } ], "code": "$runPython.success", "source": " $runPython.success" } }, "transitions": [{ "inputs": {}, "id": 15, "target": { "id": 14 }, "position": "90,600 90,630", "sourceConnector": "bottom" } ], "id": 8, "action": "gcx:wf:core::SetWorkflowOutput", "position": "-30,570", "title": "Set Success Output" }, { "inputs": { "name": "OSVariables", "value": { "accessors": ["$scriptOutput"], "annotations": [{ "kind": "idref", "index": 0, "count": 13 } ], "code": "$scriptOutput.result", "source": "$scriptOutput.result" } }, "id": 14, "action": "gcx:wf:core::SetWorkflowOutput", "position": "-30,630", "title": "Set Values Output", "description": "" }, { "inputs": {}, "transitions": [{ "inputs": {}, "id": 7, "target": { "id": 4 }, "position": "90,250 90,290", "sourceConnector": "bottom", "targetConnector": "top" } ], "id": 6, "action": "gcx:wf:core::GetWorkflowInputs", "position": "-30,140", "title": "Get Workflow Inputs", "description": "\"variableNames\" are sent as args to python script", "name": "inputs" } ], "id": 2 } ], "designerVersion": "5.11.0+28", "start": { "id": 3 } }
0 -
Tom,
Perfect! That worked. Thanks again for the example. This helps me tremendously.
Matt
0 -
Glad we could help.
The Open by URL of server workflows could be better handled (maybe even some text saying it only works for client-side workflows). It should probably just post a dialog saying it cannot import the workflow rather than randomly replacing Activities. Unfortunately, I don't see a key:value that would differentiate between a client or server workflow.
0 -
Hi @Tom Neer? . I am trying to do this exact thing, but I am not getting any results. I found a thread that in order for the python to run, I needed to set the identity of the GeocortexWorkflow application pool to the local admin, which I have, but it is still not working. Could you help please?
0 -
@Linda Stewart? We actually do not recommend using a local admin for the GeocortexWorkflow app pool. It is a huge security hole.
We scratched our head for sometime on this one. It's not well documented. What works for us is to assign permissions to the GeocortexWorkflow app pool to the document. This is a bit tricky. You can't search for this account.
- Right-click on the file you want to give Workflow access to and select Properties
- Select the Security tab and click on Edit
- In the Permissions dialog, click Add
- In the Select Users [...] dialog:
- Make sure that your Location is set to you local server, not an AD controller
- Enter "IIS AppPool\GeocortexWorkflow" into the Object Name text field and click Check Names. This should change to GeocortexWorkflow (underlined), if you did it correctly.
- Click OK
- Assign your permissions as appropriate for your application.
Hope that helps.
Best
-Tom
0 -
Thanks @Tom Neer . Still doesn't work for me. It doesn't run the python, the JobResult.success is false. Is there anything else I should check or change? Thank you!
0 -
Also, I'm seeing the same errors as this thread https://communities.geocortex.com/s/question/0D5f200006YXWC4CAP/server-workflow-the-ticket-is-not-valid , but I checked and the workflow is not referencing itself. Not sure if the issue is in accessing the server workflow or the python in the server workflow
0 -
That error sounds like the issue is access to the server workflow... but then I wouldn't expect you to see any JobResult from the python activity so this is confusing. Perhaps it belies a permissions issue with your python file? We have found that keeping the python scripts in the ":\ProgramData\Geocortex\Workflow\" directory to be helpful with this.
0 -
I have tried these things, but all have failed.
- placed python in "c:\programdata\geocortex\workflow\pythonscripts" and added GeocortexWorkflow appPool to the security of the python script
- placed python in a shared folder on the server "\\<serverName>\<sharedFolder>\scripts\"
- specified admin as the identity on the geocortexWorkflow appPool (I know it's not recommended, but I wanted to see if it will work -- it didn't)
If the issue is accessing the python, is there a way for me to positively test that? if it's just the server workflow itself, is there a way to test that?
0 -
I had to modify one more IIS setting to get mine to work correctly. Under the advanced settings for the Workflow application pool, I had to set 'Load Profile' to true.
0 -
?I was so hopeful! Thank you @Matt Palavido?, but that did not fix it for me.
I'm assuming there are 3 points of possible failure.
- That the client workflow cannot access the server workflow
- that the server workflow cannot access the server
- that the python is not being executed
I created another server workflow that has the copy file activity. After running the client side workflow to call the server workflow, I checked the new location and the file is copied which means there is not a problem with scenarios 1 & 2. So does that mean it was a problem with scenario 3?
There is python2.7 and 3.6 on the server so maybe it doesn't know which to use to execute the python? The code is so simple, I would not think it would matter which version is used.
But the "success" outputs is false which tells me the python did run but had issues?
0 -
So I sent a support case to Latitude about my issue and they are saying it's a bug.
Bug: 26675. Not sure from my issue or this was already an identified bug. ?
0 -
@Linda Stewart? You can still call Workflow 4 and use the scripting in there.
0 -
@DDS Technical Support? I created a workflow 4 and put in a very simple c# script to call a batch file. it didn't throw any errors, but also didn't do anything, certainly did not invoke the batch file. Do you have any advice on how to make this work??
0 -
Got this working based on Tom's initial comment above, with the python script re-formatted below. But grabbed the Server workflow json from Tom's comment here and imported into wf designer. Didnt use the server wf from initial comment (agol item url), has no Run Python activity in it. Used wf designer on a local pc, version 5.29.0, and storing items in arcgis online.
""" Title: Get OS Environment Variables
Description: Quick script that takes a list of os environment variable keys and returns a JSON string of the key:value pairs.
If a variable does not exist, "ERROR: OS Variable not found." is returned.
Requires: Written in Python 3.7.3 but should work in all current versions of Python.
:ORGANIZATION: geoWidgets by Digital Data Services, Inc. :CONTACT: https://www.geowidgets.io :UPDATED: 2019-06-24 """
from json import dumps
from os import environ
from sys import argvdef main(env_variables):
# Skip first argv, which is the script source
keys = env_variables[1:]
# Set keys that the server is allowed to return
denylisted_keys = []
# Denylist has precedence over allowlist
allowlisted_keys = ['TEMP', 'TMP', 'geowidgets_demo', 'USERNAME', 'password', 'windir']
""" Takes a list of keys and searches for then in the OS environment variables. Returns a JSON formatted string of keys and values. :param keys: String list of OS environment variables :return: JSON string of key:value pairs """
use_allowlist = len(allowlisted_keys) > 0
env_dict = {}
for key in keys:
if (key not in environ) or (key in denylisted_keys) or (use_allowlist and key not in allowlisted_keys):
# Withhold secret keys, provide same message for secrets and novalues to be sneaky
env_dict[key] = 'ERROR: No OS variable "%s" found.' % key
else:
# Add environment to output dictionary
env_dict[key] = environ[key]
return dumps(env_dict)if __name__ == '__main__':
main(env_variables)0
Bitte melden Sie sich an, um einen Kommentar zu hinterlassen.
Kommentare
17 Kommentare