1

I have created a .bashrc file using:

touch ~/.bashrc

and I am trying to get all the variables in it to be environment variables in my current environment. I saw online that you can source into it as source ~/.bashrc but nothing changed when I did this (I could not access the variables), however I could run cat ~/.bashrc and still see the variable names as the key and the variables as the password.

I tried to also loop through it as

import os

# open the .bashrc file in the home directory (~/)
with open('~/.bashrc') as f:
    # read the lines in the file
    lines = f.readlines()

# iterate over the lines in the file
for line in lines:
    # split the line into parts
    parts = line.split('=')
    # if the line has the correct format (key=value)
    if len(parts) == 2:
        # extract the key and value
        key, value = parts
        # remove any leading or trailing whitespace from the key and value
        key = key.strip()
        value = value.strip()
        # set the key as an environment variable with the corresponding value
        os.environ[key] = value

but the open did not run, giving the error.

FileNotFoundError: [Errno 2] No such file or directory: '~/.bashrc'

How can I import all the variables in my .bashrc file ?

user4933
  • 1,485
  • 3
  • 24
  • 42
  • 1
    Don't try; wrong approach altogether; .bashrc can contain any legal shell syntax so it can't reliably be parsed by anything but a shell. If you want a file with assignments, create such a file in a format it's easy for both Python and bash to parse (personally I prefer NUL-delimited `key=value` pairs, which is the format in which the Linux kernel exposes `/proc/self/environ`) – Charles Duffy Jan 03 '23 at 15:17
  • 1
    Also, it's common to put things in a bashrc that aren't ever supposed to go in the environment. Take PS1 as an example -- its format varies from shell to shell so it's supposed to be a process local variable that isn't exported so child processes that launch a different shell with a different format don't try to use an incompatible prompt string. – Charles Duffy Jan 03 '23 at 15:22

2 Answers2

1

source only makes sense in the context of a shell (usually a bash shell - . is the more portable POSIX equivalent). You can't meaningfully use it in a python script to update your environment. You have to source the file that contains your environment variables in a shell and then run the python script - it will inherit the environment including your new variables.

~ is also a shell-specific expansion (see Tilde Expansion). Python by default will assume that ~ is a literal pathname, you need to use os.path.expanduser to perform a Tilde Expansion similar to what the shell does.

If you want to open the file and parse it in python, you'd open it like this:

with open(os.path.expanduser('~/.bashrc')) as f:
  lines = f.readlines()

Sourcing it before running the script might be easier if you can do so:

#!/bin/bash
source ~/.bashrc
/path/to/pythonscript
tjm3772
  • 2,346
  • 2
  • 10
  • 1
    Reading the lines is the easy part. Parsing and executing shell syntax from Python is what makes this question interesting (or, I'd argue, in need of reframing into a more workable request). – Charles Duffy Jan 03 '23 at 15:20
  • I think parsing and executing is relatively straightforward as long as you assume the data is well-formed (i.e. no `=` in the value of a desired env var). OP's immediate problem is the error message which I believe comes from the misunderstanding of how `~` works. But the better solution is to not parse at all, so I agree on the reframing portion. – tjm3772 Jan 03 '23 at 15:23
  • It's not just assuming that it's well-formed, it's also assuming that content is _data_ as opposed to code. If you have a `if [[ $- = *i* ]]; then` surrounding extra assignments, how do you want to handle that? If your assignment refers to other variables with expansions, how do you want to handle _that_? If there's a function definition, you need to parse it enough to figure out where it ends so you can go back to looking for variable assignments... etc, etc, etc. – Charles Duffy Jan 03 '23 at 16:28
  • Also, bash allows multi-line assignments, so processing `lines` is potentially wrong on its face; if one has a line `foo='`, then a line `bar=baz`, then a line `qux=meh'`, that all goes into `foo` _and_ it's perfectly well-formed (insofar as it's completely compliant with POSIX sh syntax, much less bash's own extended syntax). – Charles Duffy Jan 03 '23 at 16:29
  • And then you've got things like `foo='bar'"baz"'qux'meh"` assigning the value `barbazqux'meh` (all the quotes except that one are syntactic rather than literal). Granted, `shlex.split` will handle most of those cases, but it only knows POSIX-standard syntax, not bash extensions. And while bash knows that `'foo=bar'` shouldn't be treated as an assignment because of the quotes, Python's shlex _doesn't_ know that. – Charles Duffy Jan 03 '23 at 16:30
  • (typed the above on a phone and got a character wrong; should have been `foo='bar'"baz""qux'meh"` to have the stated value while demonstrating just how grotty shell parsing gets) – Charles Duffy Jan 04 '23 at 00:36
0

You are trying to do things in the opposite direction, you don't have to parse a bash file in python.

I saw online that you can source into it as source ~/.bashrc but nothing changed

You may not have the correct content in ~/.bashrc.

Example:

# .bashrc
export MYVAR=myval
othervar=otherval
#! /usr/bin/env python3
# mypython

import os
print(os.environ)

then

source ~/.bashrc
./mypython

prints something like

environ({..., 'MYVAR': 'myval', ...})
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134