thorough
thorough

Reputation: 63

DYLD_LIBRARY_PATH and LD_LIBRARY_PATH cannot be used by python's os and subprocess modules on macOS Sierra

On macOS Sierra 10.12.6, environment variable LD_LIBRARY_PATH cannot be used by os.system(), subprocess.run() and subprocess.Popen(), even though PATH can be used normally. Python version is 3.6.1. But on Linux(Ubuntu 17.10), this environment variable can also be used rightly. The following python script envv.py can show this problem:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import subprocess
import os
import time

PATH = "PATH"
print(os.environ.get(PATH))
os.system("echo $" + PATH)
subprocess.run("echo $" + PATH, shell=True)
subprocess.run("/bin/echo $" + PATH, shell=True)
subprocess.run("/bin/echo $" + PATH, shell=True, env={PATH: os.environ.get(PATH)})
subprocess.run("/bin/echo $" + PATH, shell=True, env=os.environ)
subprocess.Popen("/bin/echo $" + PATH, shell=True, env=os.environ.copy())
time.sleep(2)
print('\n')

LD_LIBRARY_PATH = "LD_LIBRARY_PATH"
print(os.environ.get(LD_LIBRARY_PATH))
os.system("echo $" + LD_LIBRARY_PATH)
subprocess.run("/bin/echo $" + LD_LIBRARY_PATH, shell=True)
subprocess.run("/bin/echo $" + LD_LIBRARY_PATH, shell=True, env={LD_LIBRARY_PATH: os.environ.get(LD_LIBRARY_PATH)})
subprocess.run("/bin/echo $" + LD_LIBRARY_PATH, shell=True, env=os.environ)
subprocess.Popen("/bin/echo $" + LD_LIBRARY_PATH, shell=True, env=os.environ.copy())
time.sleep(2)
print('\n')

On macOS, the output is

$ python3 envv.py 
/opt/alps/bin:...
/opt/alps/bin:...
/opt/alps/bin:...
/opt/alps/bin:...
/opt/alps/bin:...
/opt/alps/bin:...
/opt/alps/bin:...


/opt/alps/lib:...
$    # use $ to show blank line
$
....

On Linux, the output is

$ python3 envv.py 
/opt/intel/compilers_and_libraries_2018.1.163/linux/bin/intel64:...
/opt/intel/compilers_and_libraries_2018.1.163/linux/bin/intel64:...
/opt/intel/compilers_and_libraries_2018.1.163/linux/bin/intel64:...
/opt/intel/compilers_and_libraries_2018.1.163/linux/bin/intel64:...
/opt/intel/compilers_and_libraries_2018.1.163/linux/bin/intel64:...
/opt/intel/compilers_and_libraries_2018.1.163/linux/bin/intel64:...
/opt/intel/compilers_and_libraries_2018.1.163/linux/bin/intel64:...


/opt/intel/compilers_and_libraries_2018.1.163/linux/compiler/lib/intel64:...
/opt/intel/compilers_and_libraries_2018.1.163/linux/compiler/lib/intel64:...
/opt/intel/compilers_and_libraries_2018.1.163/linux/compiler/lib/intel64:...
/opt/intel/compilers_and_libraries_2018.1.163/linux/compiler/lib/intel64:...
/opt/intel/compilers_and_libraries_2018.1.163/linux/compiler/lib/intel64:...
/opt/intel/compilers_and_libraries_2018.1.163/linux/compiler/lib/intel64:...

Does anyone have any idea? Thanks a lot!

UPDATE 2018-02-07

Follow @GrahamDumpleton 's suggestion, I tried DYLD_LIBRARY_PATH, but got the same result. The test stript is

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import subprocess
import os

DYLD_LIBRARY_PATH = "DYLD_LIBRARY_PATH"
print(os.environ.get(DYLD_LIBRARY_PATH))
os.system("echo $" + DYLD_LIBRARY_PATH)
subprocess.run("/bin/echo $" + DYLD_LIBRARY_PATH, shell=True)
subprocess.run("/bin/echo $" + DYLD_LIBRARY_PATH, shell=True, env={DYLD_LIBRARY_PATH: os.environ.get(DYLD_LIBRARY_PATH)})
subprocess.run("/bin/echo $" + DYLD_LIBRARY_PATH, shell=True, env=os.environ)
subprocess.Popen("/bin/echo $" + DYLD_LIBRARY_PATH, shell=True, env=os.environ.copy())

And the related output is

$ python3 envv.py
/opt/intel/compilers_and_libraries_2018.1.126/mac/compiler/lib:...
$
$
...

Upvotes: 4

Views: 3666

Answers (1)

micah
micah

Reputation: 48

If you're using subprocess.Popen with shell=True, you can manually propagate the LD_LIBRARY_PATH and DYLD_LIBRARY_PATH variables like so:

import os
import sys
import subprocess

cmd = "/bin/echo $DYLD_LIBRARY_PATH"

sys_env = os.environ.copy()

# We've used os.environ.copy() so we can make mods
# to the subprocess environment if needed without
# affecting the parent process.

if sys.platform == 'darwin':
    if "LD_LIBRARY_PATH" in sys_env:
        cmd = f"export LD_LIBRARY_PATH={sys_env['LD_LIBRARY_PATH']} && {cmd}"
    if "DYLD_LIBRARY_PATH" in sys_env:
        cmd = f"export DYLD_LIBRARY_PATH={sys_env['DYLD_LIBRARY_PATH']} && {cmd}"

process = subprocess.Popen(
    cmd,
    env=sys_env,
    shell=True,
)

Upvotes: 2

Related Questions