Skip to main content
Question

Pass Control Room file (.env) variable to Python function

  • November 17, 2025
  • 11 replies
  • 63 views

Forum|alt.badge.img+2

Hello Community,


I tested the Python script in Automation Anywhere and it works fine when I run it locally — it loads everything correctly from the .env file using load_dotenv.

Then uploaded the .env file into Control Room and created an input variable called demo_env.

Then I added the wrapper file with the demo_env parameter.
 


 


But whenever I run it from AA, it fails and says there’s an issue in the code — even though it works perfectly when using the local .env path.

Can someone take a look? I’m not sure what’s going wrong here.

 

def aa_wrapper(demo_env, search_terms=None, days=None, use_database=True):
"""AA wrapper with schedule checking"""
start_time = datetime.datetime.now()

try:
logger.info("=== CVE Check AA Wrapper Started ===")
#env_path=r"\Bots\dev_bot\euo\.env"
#env_path=demo_env
# Handle if demo_env is a file object or string
if hasattr(demo_env, 'path'):
env_path = demo_env.path
elif hasattr(demo_env, '__str__'):
env_path = str(demo_env)
else:
env_path = demo_env

path = env_path
#path = env_path or DEFAULT_ENV_PATH

if not os.path.exists(path):
error_msg = f"ERROR: .env file not found at {path}"
logger.error(error_msg)
return error_msg

from dotenv import load_dotenv
load_dotenv(dotenv_path=path, override=True)
logger.info("Environment variables loaded")

error_log_path = os.getenv("CVE_LOG_PATH", "cve_check_error.log")
setup_logging(error_log_path)

should_run, reason = should_run_cve_check()

if not should_run:
logger.info("=== CVE Check Skipped ===")
logger.info(reason)
return f"SKIPPED: {reason}"

terms_list = DEFAULT_SEARCH_TERMS
if search_terms:
terms_list = [term.strip().lower() for term in search_terms.split(',')]
logger.info(f"Using search terms: {terms_list}")

days_to_use = DEFAULT_DAYS
if days:
days_to_use = min(int(days), 120)
logger.info(f"Using days: {days_to_use}")

logger.info("Starting CVE check")
success = main_cve_check(terms_list, days_to_use, True, use_database)

elapsed = (datetime.datetime.now() - start_time).total_seconds()

db_status = " (with database)" if use_database else " (no database)"

if success:
success_msg = f"SUCCESS: CVE check completed in {elapsed:.2f}s{db_status}. {reason}"
logger.info(success_msg)
return success_msg
else:
error_msg = f"FAILED: CVE check failed after {elapsed:.2f}s"
logger.error(error_msg)
return error_msg

except Exception as e:
elapsed = (datetime.datetime.now() - start_time).total_seconds()
error_msg = f"ERROR: {e} after {elapsed:.2f}s"
logger.error(error_msg)
logger.error("Exception:", exc_info=True)
return error_msg

 

11 replies

Aaron.Gleason
Automation Anywhere Team
Forum|alt.badge.img+14
  • Automation Anywhere Team
  • November 17, 2025

@DanC25 Python probably doesn’t like our File variable. It’s not just a String holding a path, it’s a whole other beast.

If you need to pass a file to Python, I would recommend putting a copy somewhere that Python can access it and passing the path to the file, letting Python open the file itself.

 


Forum|alt.badge.img+2
  • Author
  • Cadet | Tier 2
  • November 17, 2025

@Aaron.Gleason 

thanks

Is there any way in AA to pass the .env file’s content to the bot so it can load the variables exactly like it does when running locally? and how ?

The .env contains credentials, so I’d prefer to store it in the AA Control Room instead of keeping it on the local machine.


Aaron.Gleason
Automation Anywhere Team
Forum|alt.badge.img+14
  • Automation Anywhere Team
  • November 17, 2025

@DanC25 Good question. If the .env file is in XML or JSON format, you could load the object from the control room file, then send the message to a String variable in its native format. 

Is this is a text file, you can use the CSV/TXT actions (along with Loop and some Data Table actions) to read the file contents to a String variable.

Let me know the format and I can propose some AA code for you.


Forum|alt.badge.img+2
  • Author
  • Cadet | Tier 2
  • November 17, 2025

@Aaron.Gleason 
thanks


.env is plain text as below :
 

ERROR_LOG_PATH_DownloadMail_ol=C:\Users\xxx\xxx.log
ERROR_LOG_PATH_bkpTemp=C:\Users\xxx\xxx.log
ERROR_LOG_PATH_preprocsv= C:\Users\xxx\xxx.log
ERROR_LOG_PATH_onepiecemonthlysummary=C:\Users\xxx\xxx.log

ERROR_LOG_PATH_thon_cvlt=C:\Users\xxx\xxx.log
CVE_LOG_PATH=C:\Users\xxx\xxx.log
DB_HOST="xxx"
DB_NAME="xxx_db"
DB_USER="xxx"
DB_PASSWORD="xxx#xxx"

CVE_AUTO_REPEAT=true
CVE_REPEAT_HOURS=12
# Add these environment variables to your .env file:

# CVE Alert Configuration
CVE_ALERT_ENABLED=true
CVE_ALERT_RECIPIENTS=xxx@xxx.com
CVE_ALERT_CC=xxx@xx.com,xxx@xxx.com
CVE_REGULAR_RECIPIENTS=xxx@xxx.com
CVE_REGULAR_CC=xxx@xxx.com
 

 


Aaron.Gleason
Automation Anywhere Team
Forum|alt.badge.img+14
  • Automation Anywhere Team
  • November 17, 2025

@DanC25 The quickest way to read that .env file from your Control Room into a String variable is something like this:

Since the .env file can’t be read by the CSV/TXT package, I have to download a local copy to the c:\temp folder. Then I can read it using the CSV/TXT: Read action, which reads each line into a data table variable. Then, I loop through the table and concatenate the String variable with the row contents (rTableRow[0]).


Padmakumar
Premier Pathfinder | Tier 7
Forum|alt.badge.img+15
  • Premier Pathfinder | Tier 7
  • November 18, 2025

Hi ​@DanC25,

 

In my opinion, don’t pass the File variable itself to Python. It’s not a plain path string. Either:

Option A (Recommended): Use Credential Vault, skip .env.
Fetch secrets in the bot (Credential actions), pass them as function parameters (or set them as environment variables with bot actions), and let Python read them from os.environ. Keeps creds in the Control Room and avoids file plumbing. 


Option B (if you must use .env): materialize, then pass the path.
Download the Control Room file to a local temp folder (so you have a real filesystem path), pass that string path into your Python function, call load_dotenv(dotenv_path=that_path), then delete the temp file. This aligns with why your run fails—the Python action expects a path, not AA’s File object. 

 

Either approach will match what works locally while keeping credentials in Control Room.


Forum|alt.badge.img+2
  • Author
  • Cadet | Tier 2
  • November 18, 2025

@Padmakumar 

thanks
 

I found the thread below (from ​@Aaron.Gleason ) from about four months ago saying that passing credential variables to a Python script wasn’t supported.

 


But based on your Option A, it looks like this might now be possible.
Could you share any documentation or examples on how to pass a credential vault variable(username, password, serverIP, dbname) into a Python script? thanks


Forum|alt.badge.img+2
  • Author
  • Cadet | Tier 2
  • November 18, 2025

@Padmakumar 

I’ve been digging into this, and looks like there really isn’t a supported way to pass an encrypted value directly into a Python script.

Even though Option A sounded promising, AA doesn’t actually allow it, I tried modifying the wrapper to accept DB credentials as function arguments and pass in the secret, but it errors out saying the variable isn’t allowed.

Just wondering how you were able to get this working on your side?


Padmakumar
Premier Pathfinder | Tier 7
Forum|alt.badge.img+15
  • Premier Pathfinder | Tier 7
  • November 19, 2025

@Padmakumar 

I’ve been digging into this, and looks like there really isn’t a supported way to pass an encrypted value directly into a Python script.

Even though Option A sounded promising, AA doesn’t actually allow it, I tried modifying the wrapper to accept DB credentials as function arguments and pass in the secret, but it errors out saying the variable isn’t allowed.

Just wondering how you were able to get this working on your side?

 

You’re right to call this out—the Python Script actions don’t accept Credential Vault variables directly, and AA enforces that restriction for security. Community and docs confirm that only certain actions can consume credential variables; Python Script is not one of them. 
Separately, the Execute function action only supports Boolean, dictionary, list, number, or string arguments (i.e., non‑credential types), and it exposes a single argument field (so you bundle multiple args in a list). 

Below is how I get Option A and Option B working in A360 without violating those constraints.

 

Option A (still recommended): Use Credential Vault, but stage into a normal string before Python

When you try to pass a credential variable straight into the Python function, AA blocks it. You must resolve the credential into a normal (insecure) string variable first, and only then pass that string to Python. The Credential package > Assign action is designed for this: it retrieves the value and saves it into a standard variable that your bot can use downstream. (AA hides “convert credential to string” from general use due to risk, but Assign is the supported way to get the value into a bot variable.) 
 

1. Retrieve secrets from Vault

  • Use Credential > Assign to read DB_User and DB_Pass from your locker, Save the outcome to string variables sDbUser, sDbPass.

2. Bundle arguments for Python

  • Create a List variable lArgs with items like [sDbUser, sDbPass, sHost, sDbName]. The Execute function UI supports one argument, but accepts a list to represent multiple.

3. Execute function

  • Call your Python function (e.g., init_db) with lArgs.

4. Inside Python, unpack the list and either:

  • Use them directly to connect, or
  • Set environment vars at runtime:
import os
def init_db(args):
   user, pwd, host, db = args
   os.environ["DB_USER"] = user
   os.environ["DB_PASS"] = pwd
   # Connect using user/pwd...
   return "OK"


(AA provides no special environment-variable bridge here; you simply set them in Python after receipt.)
Background docs for Python script usage and argument handling. 


Yes, this makes the secret a normal string variable inside the bot run. That’s the trade‑off AA imposes if you need to pass data into Python. Keep scope tight, avoid logging, and clear variables after use. The credential package documentation itself warns about converting credentials due to risk; we’re using the supported Assign action and managing exposure carefully. [docs.autom...ywhere.com]

I always retrieve to string variables first, pass them to Python as a list, and never pass credential types directly to Python. That aligns with AA’s limitations and avoids the variable isn’t allowed error you’re seeing.
 

 

Option B (when you must use .env): Materialize to disk, pass the path


AA explicitly advise: don’t pass the AA File variable to Python—it’s not a plain path. Instead, download the Control Room file to a local path and pass that string path. 
 

1. Download CR file

  • Use File > Get path with Control Room file to retrieve the local path where AA downloads the file, save to string sEnvLocalPath. (AA’s Get path returns the local path of a downloaded Control Room file.) 
  • Alternatively, File > Copy Control Room file to a known temp folder that you control (e.g., %TEMP%\mybot\.env) and remember that path in sEnvLocalPath. 

2. Execute function

Pass sEnvLocalPath (or a list of args) to your Python function.


3. Inside Python, load it:

import os
from dotenv import load_dotenv
def aa_wrapper(args):
   env_path = args if isinstance(args, str) else args[0]
   if not os.path.exists(env_path):
       return f"ERROR: .env file not found at {env_path}"    
load_dotenv(dotenv_path=env_path, override=True)
   # continue...
   return "OK"

4. Cleanup

  • After the Python session closes, delete the temp file.

It matches how python-dotenv expects a real file path and bypasses AA’s special File object. The community thread you linked explicitly calls out this distinction.

 

The variable isn’t allowed message appears when:

  • You were likely passing a credential variable directly to Python. By design, credential variables can only be consumed by actions that explicitly support them, not by Python Script. Hence, AA refuses it. 
  • The Execute function action enforces argument type constraints—only standard types (string/number/list/dict/boolean), not credential types.

 

Note:

  • If Python calls still fail, enable Throw an exception if the python script fails in the Execute function and check Bot Runner logs (Windows: C:\ProgramData\AutomationAnywhere\BotRunner\Logs\...) for the exact Python error. 
  • Avoid odd file/function names (test.py/test) when running from Control Room—there’s a known quirk where renaming resolves bot error.

 


Forum|alt.badge.img+2
  • Author
  • Cadet | Tier 2
  • November 19, 2025

@Padmakumar 

Thanks

You mentioned using Credential → Assign to read DB_User and DB_Pass from the locker and save them into string variables like sDbUser and sDbPass.

But even after saving them into variables, the variable type still stays as Credential, so we can’t pass it into the function arguments. Since this part doesn’t seem to work on my side, could you send me a screenshot showing how you were able to make it work?


Padmakumar
Premier Pathfinder | Tier 7
Forum|alt.badge.img+15
  • Premier Pathfinder | Tier 7
  • November 20, 2025

@Padmakumar 

Thanks

You mentioned using Credential → Assign to read DB_User and DB_Pass from the locker and save them into string variables like sDbUser and sDbPass.

But even after saving them into variables, the variable type still stays as Credential, so we can’t pass it into the function arguments. Since this part doesn’t seem to work on my side, could you send me a screenshot showing how you were able to make it work?

Well, I am using the below credential package to convert the value to a string. Sorry, I missed mentioning this in my previous response.

Credential Utilities - Bot Store