2

I can determine the width of the terminal in Python with a subprocess-handled query such as the following:

int(subprocess.Popen(['tput', 'cols'], stdout = subprocess.PIPE).communicate()[0].strip('\n'))

How could I determine the Bash user name in a similar way? So, how could I see the value of ${USER} in Python using subprocess?

Amit Joshi
  • 12,434
  • 18
  • 59
  • 118
d3pd
  • 6,679
  • 18
  • 56
  • 111
  • 2
    Why do you want to use `subprocess`? The python process itself has access to the environment. – Wooble Jul 03 '14 at 17:35
  • 3
    You can use [`os.environ`](https://docs.python.org/2/library/os.html#os.environ) for this. e.g. `print(os.environ['USER'])` – dano Jul 03 '14 at 17:36
  • Thank you very much for your suggestions. Part of the motivation is wanting to understand how to use Bash variables in ```subprocess``` methods. I am not sure how to do this. Accessing the environment variable ${USER} is a simple example. – d3pd Jul 05 '14 at 14:17
  • 1
    The thing is, calling Python subprocess with a bash-style variable name does not do any variable expansion, globbing, etc. There is no shell between Python subprocessing, and the argv/argc of the program you are invoking. – NicholasM Jul 06 '14 at 05:26
  • unrelated: there is [`shutil.get_terminal_size()` function](https://docs.python.org/3/library/shutil.html#shutil.get_terminal_size) in Python 3.3+, to get width/height of the terminal. – jfs Jul 26 '14 at 14:31

1 Answers1

5

As Wooble and dano say, don't use subprocess for this. Use os.getenv("USER") or os.environ["USER"].

If you really want to use subprocess then Popen(['bash', '-c', 'echo "$USER"'], ...) seems to work as does Popen("echo $USER", shell=True) though neither of those is particularly pleasant (though to use environment variables on the command line being executed the shell must be involved so you can't really avoid it).

Edit: My previous subprocess suggestion did not seem to work correctly. I believe my original test was flawed.

Etan Reisner
  • 68,917
  • 7
  • 78
  • 118
  • Thank you very much for your suggestions on using the ```getenv``` and ```environ``` methods of the module ```os```. This works well. Part of the motivation in wanting to use the module ```subprocess``` is wanting to understand how to use Bash variables in ```subprocess``` methods. I have tried your ```subprocess.Popen(['echo', '${USER}'])``` suggestion but am presented with '${USER}' as a response rather than the actual environment variable value in both Python 2.7.6 and 3.4.0. Do you know how to access the actual value? – d3pd Jul 06 '14 at 15:51
  • Ah, great. Your edits have made that work. Thanks again for your help! – d3pd Jul 06 '14 at 15:53
  • @d3pd: A [portable way to find out the current username in Python is `getpass.getuser()` function](http://stackoverflow.com/q/842059/4279). – jfs Jul 26 '14 at 14:35
  • @Etan Reisner: *do not* use a list argument and `shell=True` together. Always pass a string if you use `shell=True` instead. – jfs Jul 26 '14 at 14:36
  • @J.F.Sebastian Would you care to enlighten me as to why? (I am by no means a python person.) – Etan Reisner Jul 27 '14 at 03:12
  • That's stupid behaviour. Encouraging people to need to format command line arguments themselves for complicated commands is backwards. Expecting individual arguments (which can then be quoted sanely) is much better. But there are many reasons I don't do python already. Fixed post to remove the (useless anyway) list brackets. – Etan Reisner Jul 27 '14 at 11:38
  • @EtanReisner: how do you suggest to split `"a |& b"` shell command into a list? Could name a language that has a builtin shell parser for all platforms that Python supports? Note: the default is `shell=False` i.e., a shell is *not* used and the command is specified as a sequence of program arguments. – jfs Jul 27 '14 at 21:34
  • I didn't suggest that requiring list splitting is a good idea either. I said suggesting that in the default cases people ensure that they get shell quoting correct is a bad decision. Someone who knows enough to know that they want to use a shell and use `|&` in the pipeline is **significantly** more likely to be able to get shell quoting correct than is the average person trying to run a random shell command off user input. – Etan Reisner Jul 28 '14 at 16:41