1

As the title says:

>>> from subprocess import check_output
>>> check_output(['ln', '~/other_folder/src/models/sc_models.py', './src/models/sc_models.py'])
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 573, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
CalledProcessError: Command '['ln', '~/other_folder/src/models/sc_models.py', './src/models/sc_models.py']' returned non-zero exit status 1
>>> exit()
$ ln ~/other_folder/src/models/sc_models.py ./src/models/sc_models.py
$

How can this be? How can it succeed from the command line, but fail from the Python subprocess call?

All tips are welcome!

kramer65
  • 50,427
  • 120
  • 308
  • 488

1 Answers1

6

You need to use os.path.expanduser:

On Unix and Windows, return the argument with an initial component of ~ or ~user replaced by that user‘s home directory.

import os

os.path.expanduser('~/other_folder/src/models/sc_models.py')

In [2]: os.path.expanduser("~")
Out[2]: '/home/padraic'

Python is looking for a directory named ~ in your cwd which obviously fails. When you run the code from bash the ~ is expanded, unless you were to use shell=True where the command would be passed to the shell and the shell would expand the tilde then you would need to use os.path.expanduser or pass the whole path i.e /home/user/other_folder...... I would stick to using shell=False withos.path.expanduser("~").

Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • Note: the code in the question won't work even if you were to add `shell=True` because only the first list item is executed as a shell command, the rest is interpreted as the shell's arguments on POSIX. In other words: don't use a list argument and `shell=True` together, pass a string instead or (better) don't use `shell=True`: as you've shown it is enough to call `os.path.expanduser('~/...')` here. – jfs May 28 '15 at 07:06
  • @J.F.Sebastian, why does `check_call(["ls","~/"],shell=True)` work then? – Padraic Cunningham May 28 '15 at 17:55
  • Do you understand the difference between `sh -c 'cmd arg1'` (correct) and `sh -c 'cmd' arg1` (wrong)? For example, see http://bugs.python.org/issue7839 – jfs May 28 '15 at 18:40