'Using .env files to set environment variables in Windows

I am working on a set of projects that use .env files for configuration, where each .env file exports a number of environment variables. The files are setup like;

export VARIABLE1=foo

I use the Windows Linux subsystem a lot for this, but would like to also be able to run these projects on my windows machine. The projects in question are Golang.

IS there any easy way to programatically set Windows environment variables (preferably termporarily) from these .env files? These is mostly so I can debug within VSCode.



Solution 1:[1]

i used godotenv library.

Add configuration values to a .env file at the root of project:

PORT=8080
NAME=FlowAPI

main.go

package main

import (
    "log"
    "github.com/joho/godotenv"
    "fmt"
    "os"
)

func init() {
    // loads values from .env into the system
    if err := godotenv.Load(); err != nil {
        log.Print("No .env file found")
    }
}

func main() {
    // Get the PORT environment variable
    port, exists := os.LookupEnv("PORT")
    if exists {
        fmt.Println(port)
    }
}

Solution 2:[2]

Package os

import "os"

func Clearenv()
func Environ() []string
func Expand(s string, mapping func(string) string) string
func ExpandEnv(s string) string
func Getenv(key string) string
func Setenv(key, value string) error
func Unsetenv(key string) error

Read the env file lines using bufio.Scanner. Parse the lines using the strings package. Use the os package environment variable functions.

For example,

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "io"
    "os"
    "strings"
)

func parseLine(line string) (key, value string) {
    line = strings.TrimSpace(line)
    const export = `export `
    if !strings.HasPrefix(line, export) {
        return "", ""
    }
    line = strings.TrimPrefix(line, export)
    fields := strings.SplitN(line, "=", 2)
    if len(fields) > 0 {
        key = strings.TrimSpace(fields[0])
        if len(fields) > 1 {
            value = strings.TrimSpace(fields[1])
        }
    }
    return key, value
}

func setenv(r io.Reader) error {
    s := bufio.NewScanner(r)
    for s.Scan() {
        line := s.Text()
        key, value := parseLine(line)
        if len(key) < 1 {
            continue
        }
        err := os.Setenv(key, value)
        if err != nil {
            return err
        }
    }
    if err := s.Err(); err != nil {
        return err
    }
    return nil
}

func main() {
    envFile := bytes.NewBufferString(
        "export VARIABLE1=foo\r\nexport VARIABLE2=bar\n",
    )
    err := setenv(envFile)
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }
    for _, key := range []string{`VARIABLE1`, `VARIABLE2`} {
        env, found := os.LookupEnv(key)
        fmt.Println(key, found, env)
    }
}

Playground: https://play.golang.org/p/pZKQ0GW5eCu

Output:

VARIABLE1 true foo
VARIABLE2 true bar

Solution 3:[3]

Create a text file called ".env" (you could actually call it anything I guess, but this makes it brief and descriptive). Put this file in any folder of your choice... well away from any Python code you might make public, e.g. GitHub, GitLab, etc. For example, mine is located at "E:/Python/EnvironmentVariables/.env".

Edit the file in your favourite text editor, and create your secrets. You can have all of your secrets for all of your projects in this one file if you wish, [Headings] are optional and for your benefit only. Make sure all the key names are different - add the project name to the beginning or end if you wish:

[MyProject]
MyUsername="Fred Bloggs"
MyEmail="[email protected]"
MyPassword="fvghtyu7i890ol"

[MyOtherProject]
MyAPIKey_MyOtherProject="FMu4ejyK-qQLBasTs7iHx*SFN5fF"
email_port=110
DEBUG=True

Now in your python program do this to get access to any secret you want, in any project!

import os
from dotenv import load_dotenv

load_dotenv("E:/Python/EnvironmentVariables/.env")
USER_NAME = os.getenv("MyUsername")
API_KEY = os.getenv("MyAPIKey_MyOtherProject")

print(USER_NAME, API_KEY)

Solution 4:[4]

If you are on Windows, you can use powershell to read your .env file and load the key=value pairs into session-level environment variables that your app can read. Toss the code below into a file called DotEnvToEnvVars.ps1 (or whatever you want to call it). Then run the script passing the path to your .env file: C:> ./DotEnvToEnVars.ps1 ./myproject/.env -Verbose

Include optional params:

  • -Verbose to see what environment variables were set

  • -Remove to delete all the environment variables with names found in that .env file

  • -RemoveQuotes to strip the " and ' from surrounding the value side of the key/value pairs in your .env before making environment variables out of them

param(
    [string]$Path,
    [switch]$Verbose,
    [switch]$Remove,
    [switch]$RemoveQuotes
)

$variables = Select-String -Path $Path -Pattern '^\s*[^\s=#]+=[^\s]+$' -Raw

foreach($var in $variables) {
    $keyVal = $var -split '=', 2
    $key = $keyVal[0].Trim()
    $val = $RemoveQuotes ? $keyVal[1].Trim("'").Trim('"') : $keyVal[1]
    [Environment]::SetEnvironmentVariable($key, $Remove ? '' : $val)
    if ($Verbose) {
        "$key=$([Environment]::GetEnvironmentVariable($key))"
    }
}

Solution 5:[5]

Old question that got bumped today with a new answer, but there's a supported feature for doing this (wslenv) that hasn't been mentioned.

The OP mentions that they have Windows Subsystem for Linux, but they want to have the .env files that they use in WSL available in the Windows environment.

Assuming the variable names are static, this is fairly straightforward (no script/parsing necessary):

Take, for example, an .env with:

export VARIABLE1=foo
export VARIABLE2=bar
export VARIABLE3=baz

Start in WSL/Bash:

cd /mnt/c/
source /path/to/.env
# Substitute powershell.exe for older version
WSLENV=$WSLENV:VARIABLE1:VARIABLE2:VARIABLE3 pwsh.exe

You will then be in a PowerShell instance where the environment is set with the desired variables from your WSL .env file.

Executing any Windows process from there, such as code, will propagate the environment to that subprocess.

So, run code, then open a new terminal inside VSCode.

echo $env:VARIABLE1

... will correctly respond with foo.

Alternative if the variable names are dynamic

Or convenience method for collecting the variable names

If you want to just generate a list of the variables from your .env file, something like the following will work:

In WSL/Bash:

source ./.env
for v in $(sed -E 's/export *([^=]*).*/\1/' ./.env); do export WSLENV=$WSLENV:$v; done
# Substitute powershell.exe for older version
pwsh.exe

That will process the .env file to look for the variable names that need to be added to the $WSLENV variable.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 sh.seo
Solution 2
Solution 3 SadSack963
Solution 4 nc1943
Solution 5 NotTheDr01ds