Skip to content

Commit 5b1139c

Browse files
wangqryifeif
authored andcommitted
Clean up 'shell=True' in using subprocess module (tensorflow#12347)
* Set default shell=False in configure.py * Fix wrong paths when building for other python * Clean up 'shell=True' in using subprocess module * Fix a regexp in configure.py * Check existence before executing For platform specific commands, use python functions instead if possible * Fix typo in input prompt * Fix a ldconfig mistake made in 3b6db82
1 parent f4117af commit 5b1139c

File tree

4 files changed

+81
-70
lines changed

4 files changed

+81
-70
lines changed

configure.py

Lines changed: 61 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
import subprocess
2626
import sys
2727

28+
try:
29+
from shutil import which
30+
except ImportError:
31+
from distutils.spawn import find_executable as which
32+
2833
_TF_BAZELRC = '.tf_configure.bazelrc'
2934
_DEFAULT_CUDA_VERSION = '8.0'
3035
_DEFAULT_CUDNN_VERSION = '6'
@@ -53,6 +58,10 @@ def is_ppc64le():
5358
return platform.machine() == 'ppc64le'
5459

5560

61+
def is_cygwin():
62+
return platform.system().startswith('CYGWIN_NT')
63+
64+
5665
def get_input(question):
5766
try:
5867
try:
@@ -121,13 +130,20 @@ def write_action_env_to_bazelrc(var_name, var):
121130
write_to_bazelrc('build --action_env %s="%s"' % (var_name, str(var)))
122131

123132

124-
def run_shell(cmd):
125-
return subprocess.check_output(cmd, shell=True).decode('UTF-8').strip()
133+
def run_shell(cmd, allow_non_zero=False):
134+
if allow_non_zero:
135+
try:
136+
output = subprocess.check_output(cmd)
137+
except subprocess.CalledProcessError as e:
138+
output = e.output
139+
else:
140+
output = subprocess.check_output(cmd)
141+
return output.decode('UTF-8').strip()
126142

127143

128144
def cygpath(path):
129145
"""Convert path from posix to windows."""
130-
return run_shell('cygpath -m "%s"' % path)
146+
return run_shell(['cygpath', '-m', path])
131147

132148

133149
def get_python_path(environ_cp, python_bin_path):
@@ -136,16 +152,14 @@ def get_python_path(environ_cp, python_bin_path):
136152
if environ_cp.get('PYTHONPATH'):
137153
python_paths = environ_cp.get('PYTHONPATH').split(':')
138154
try:
139-
check_input = [python_bin_path, '-c',
140-
'import site; print("\\n".join(site.getsitepackages()))']
141-
library_paths = subprocess.check_output(
142-
check_input).decode('UTF-8').strip().split("\n")
155+
library_paths = run_shell(
156+
[python_bin_path, '-c',
157+
'import site; print("\\n".join(site.getsitepackages()))']).split("\n")
143158
except subprocess.CalledProcessError:
144-
check_input = [python_bin_path, '-c',
145-
'from distutils.sysconfig import get_python_lib;' +
146-
'print(get_python_lib())']
147-
library_paths = [subprocess.check_output(
148-
check_input).decode('UTF-8').strip()]
159+
library_paths = [run_shell(
160+
[python_bin_path, '-c',
161+
'from distutils.sysconfig import get_python_lib;'
162+
'print(get_python_lib())'])]
149163

150164
all_paths = set(python_paths + library_paths)
151165

@@ -158,8 +172,7 @@ def get_python_path(environ_cp, python_bin_path):
158172

159173
def get_python_major_version(python_bin_path):
160174
"""Get the python major version."""
161-
check_input = [python_bin_path, '-c', 'import sys; print(sys.version[0])']
162-
return subprocess.check_output(check_input).decode('UTF-8').strip()
175+
return run_shell([python_bin_path, '-c', 'import sys; print(sys.version[0])'])
163176

164177

165178
def setup_python(environ_cp, bazel_version):
@@ -173,8 +186,8 @@ def setup_python(environ_cp, bazel_version):
173186
environ_cp, 'PYTHON_BIN_PATH', ask_python_bin_path,
174187
default_python_bin_path)
175188
# Check if the path is valid
176-
if (os.path.isfile(python_bin_path) and os.access(
177-
python_bin_path, os.X_OK)) or (os.path.isdir(python_bin_path)):
189+
if os.path.isfile(python_bin_path) and os.access(
190+
python_bin_path, os.X_OK):
178191
break
179192
elif not os.path.exists(python_bin_path):
180193
print('Invalid python path: %s cannot be found.' % python_bin_path)
@@ -183,7 +196,7 @@ def setup_python(environ_cp, bazel_version):
183196
environ_cp['PYTHON_BIN_PATH'] = ''
184197

185198
# Convert python path to Windows style before checking lib and version
186-
if is_windows():
199+
if is_cygwin():
187200
python_bin_path = cygpath(python_bin_path)
188201

189202
# Get PYTHON_LIB_PATH
@@ -193,20 +206,20 @@ def setup_python(environ_cp, bazel_version):
193206
if environ_cp.get('USE_DEFAULT_PYTHON_LIB_PATH') == '1':
194207
python_lib_path = python_lib_paths[0]
195208
else:
196-
print('Found possible Python library paths:\n%s' %
197-
'\n'.join(python_lib_paths))
209+
print('Found possible Python library paths:\n %s' %
210+
'\n '.join(python_lib_paths))
198211
default_python_lib_path = python_lib_paths[0]
199212
python_lib_path = get_input(
200-
'Please input the desired Python library path to use. Default is %s'
201-
% python_lib_paths[0])
213+
'Please input the desired Python library path to use. '
214+
'Default is [%s]\n' % python_lib_paths[0])
202215
if not python_lib_path:
203216
python_lib_path = default_python_lib_path
204217
environ_cp['PYTHON_LIB_PATH'] = python_lib_path
205218

206219
python_major_version = get_python_major_version(python_bin_path)
207220

208221
# Convert python path to Windows style before writing into bazel.rc
209-
if is_windows():
222+
if is_cygwin():
210223
python_lib_path = cygpath(python_lib_path)
211224

212225
# Set-up env variables used by python_configure.bzl
@@ -428,11 +441,10 @@ def check_bazel_version(min_version):
428441
Returns:
429442
The bazel version detected.
430443
"""
431-
try:
432-
curr_version = run_shell('bazel --batch version')
433-
except subprocess.CalledProcessError:
444+
if which('bazel') is None:
434445
print('Cannot find bazel. Please install bazel.')
435446
sys.exit(0)
447+
curr_version = run_shell(['bazel', '--batch', 'version'])
436448

437449
for line in curr_version.split('\n'):
438450
if 'Build label: ' in line:
@@ -524,7 +536,7 @@ def get_from_env_or_user_or_default(environ_cp, var_name, ask_for_var,
524536

525537
def set_clang_cuda_compiler_path(environ_cp):
526538
"""Set CLANG_CUDA_COMPILER_PATH."""
527-
default_clang_path = run_shell('which clang || true')
539+
default_clang_path = which('clang') or ''
528540
ask_clang_path = ('Please specify which clang should be used as device and '
529541
'host compiler. [Default is %s]: ') % default_clang_path
530542

@@ -547,12 +559,12 @@ def set_clang_cuda_compiler_path(environ_cp):
547559

548560
def set_gcc_host_compiler_path(environ_cp):
549561
"""Set GCC_HOST_COMPILER_PATH."""
550-
default_gcc_host_compiler_path = run_shell('which gcc || true')
562+
default_gcc_host_compiler_path = which('gcc') or ''
551563
cuda_bin_symlink = '%s/bin/gcc' % environ_cp.get('CUDA_TOOLKIT_PATH')
552564

553565
if os.path.islink(cuda_bin_symlink):
554566
# os.readlink is only available in linux
555-
default_gcc_host_compiler_path = run_shell('readlink %s' % cuda_bin_symlink)
567+
default_gcc_host_compiler_path = os.path.realpath(cuda_bin_symlink)
556568

557569
ask_gcc_path = (
558570
'Please specify which gcc should be used by nvcc as the '
@@ -587,7 +599,7 @@ def set_tf_cuda_version(environ_cp):
587599

588600
# Find out where the CUDA toolkit is installed
589601
default_cuda_path = _DEFAULT_CUDA_PATH
590-
if is_windows():
602+
if is_cygwin():
591603
default_cuda_path = cygpath(
592604
environ_cp.get('CUDA_PATH', _DEFAULT_CUDA_PATH_WIN))
593605
elif is_linux():
@@ -628,7 +640,7 @@ def set_tf_cuda_version(environ_cp):
628640
def set_tf_cunn_version(environ_cp):
629641
"""Set CUDNN_INSTALL_PATH and TF_CUDNN_VERSION."""
630642
ask_cudnn_version = (
631-
'"Please specify the cuDNN version you want to use. '
643+
'Please specify the cuDNN version you want to use. '
632644
'[Leave empty to default to cuDNN %s.0]: ') % _DEFAULT_CUDNN_VERSION
633645

634646
while True:
@@ -647,7 +659,7 @@ def set_tf_cunn_version(environ_cp):
647659
# unusable. Going through one more level of expansion to handle that.
648660
cudnn_install_path = os.path.realpath(
649661
os.path.expanduser(cudnn_install_path))
650-
if is_windows():
662+
if is_cygwin():
651663
cudnn_install_path = cygpath(cudnn_install_path)
652664

653665
if is_windows():
@@ -669,12 +681,10 @@ def set_tf_cunn_version(environ_cp):
669681

670682
# Try another alternative for Linux
671683
if is_linux():
672-
if subprocess.call(['which', 'ldconfig']):
673-
ldconfig_bin = '/sbin/ldconfig'
674-
else:
675-
ldconfig_bin = 'ldconfig'
676-
cudnn_path_from_ldconfig = run_shell(
677-
r'%s -p | sed -n "s/.*libcudnn.so .* => \(.*\)/\\1/p"' % ldconfig_bin)
684+
ldconfig_bin = which('ldconfig') or '/sbin/ldconfig'
685+
cudnn_path_from_ldconfig = run_shell([ldconfig_bin, '-p'])
686+
cudnn_path_from_ldconfig = re.search('.*libcudnn.so .* => (.*)',
687+
cudnn_path_from_ldconfig).group(1)
678688
if os.path.exists('%s.%s' % (cudnn_path_from_ldconfig, tf_cudnn_version)):
679689
cudnn_install_path = os.path.dirname(cudnn_path_from_ldconfig)
680690
break
@@ -707,11 +717,15 @@ def get_native_cuda_compute_capabilities(environ_cp):
707717
"""
708718
device_query_bin = os.path.join(
709719
environ_cp.get('CUDA_TOOLKIT_PATH'), 'extras/demo_suite/deviceQuery')
710-
cmd = (r'"%s" | grep "Capability" | grep -o "[0-9]*\.[0-9]*" | sed '
711-
'":a;{N;s/\\n/,/};ba"') % device_query_bin
712-
try:
713-
output = run_shell(cmd)
714-
except subprocess.CalledProcessError:
720+
if os.path.isfile(device_query_bin) and os.access(device_query_bin, os.X_OK):
721+
try:
722+
output = run_shell(device_query_bin).split('\n')
723+
pattern = re.compile('[0-9]*\\.[0-9]*')
724+
output = [pattern.search(x) for x in output if 'Capability' in x]
725+
output = ','.join(x.group() for x in output if x is not None)
726+
except subprocess.CalledProcessError:
727+
output = ''
728+
else:
715729
output = ''
716730
return output
717731

@@ -792,7 +806,7 @@ def set_other_cuda_vars(environ_cp):
792806

793807
def set_host_cxx_compiler(environ_cp):
794808
"""Set HOST_CXX_COMPILER."""
795-
default_cxx_host_compiler = run_shell('which g++ || true')
809+
default_cxx_host_compiler = which('g++') or ''
796810
ask_cxx_host_compiler = (
797811
'Please specify which C++ compiler should be used as'
798812
' the host C++ compiler. [Default is %s]: ') % default_cxx_host_compiler
@@ -815,7 +829,7 @@ def set_host_cxx_compiler(environ_cp):
815829

816830
def set_host_c_compiler(environ_cp):
817831
"""Set HOST_C_COMPILER."""
818-
default_c_host_compiler = run_shell('which gcc || true')
832+
default_c_host_compiler = which('gcc') or ''
819833
ask_c_host_compiler = (
820834
'Please specify which C compiler should be used as the'
821835
' host C compiler. [Default is %s]: ') % default_c_host_compiler
@@ -869,9 +883,9 @@ def set_computecpp_toolkit_path(environ_cp):
869883

870884
def set_mpi_home(environ_cp):
871885
"""Set MPI_HOME."""
872-
cmd = ('dirname $(dirname $(which mpirun)) || dirname $(dirname $(which '
873-
'mpiexec)) || true')
874-
default_mpi_home = run_shell(cmd)
886+
default_mpi_home = which('mpirun') or which('mpiexec') or ''
887+
default_mpi_home = os.path.dirname(os.path.dirname(default_mpi_home))
888+
875889
ask_mpi_home = ('Please specify the MPI toolkit folder. [Default is %s]: '
876890
) % default_mpi_home
877891
while True:

tensorflow/tools/ci_build/update_version.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ def check_all_files():
7171

7272
def replace_with_sed(query, filename):
7373
"""Replace with sed when regex is required."""
74-
subprocess.check_call("sed -i -r -e \"%s\" \"%s\"" % (query, filename),
75-
shell=True)
74+
subprocess.check_call(['sed', '-i', '-r', '-e', query, filename])
7675

7776

7877
class Version(object):
@@ -277,9 +276,8 @@ def check_for_lingering_string(lingering_string):
277276
"""Check for given lingering strings."""
278277
formatted_string = lingering_string.replace(".", r"\.")
279278
try:
280-
linger_strs = subprocess.check_output("grep -rnoH \"%s\" \"%s\""
281-
% (formatted_string, TF_SRC_DIR),
282-
shell=True).split("\n")
279+
linger_strs = subprocess.check_output(
280+
['grep', '-rnoH', formatted_string, TF_SRC_DIR]).split("\n")
283281
except subprocess.CalledProcessError:
284282
linger_strs = []
285283

tensorflow/tools/pip_package/check_load_py_test.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ def main():
4242
# Get all py_test target, note bazel query result will also include
4343
# cuda_py_test etc.
4444
try:
45-
targets = subprocess.check_output(
46-
'bazel query "kind(py_test, //tensorflow/contrib/... + '
45+
targets = subprocess.check_output([
46+
'bazel', 'query',
47+
'kind(py_test, //tensorflow/contrib/... + '
4748
'//tensorflow/python/... - '
48-
'//tensorflow/contrib/tensorboard/...)"',
49-
shell=True).strip()
49+
'//tensorflow/contrib/tensorboard/...)']).strip()
5050
except subprocess.CalledProcessError as e:
5151
targets = e.output
5252

@@ -68,9 +68,8 @@ def main():
6868
files_missing_load = []
6969
for build_file in build_files:
7070
updated_build_file = subprocess.check_output(
71-
'buildozer -stdout "new_load //tensorflow:tensorflow.bzl py_test" ' +
72-
build_file,
73-
shell=True)
71+
['buildozer', '-stdout', 'new_load //tensorflow:tensorflow.bzl py_test',
72+
build_file])
7473
with open(build_file, 'r') as f:
7574
if f.read() != updated_build_file:
7675
files_missing_load.append(build_file)

tensorflow/tools/pip_package/pip_smoke_test.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,16 @@
2525

2626
import subprocess
2727

28-
PIP_PACKAGE_QUERY = """bazel query \
29-
'deps(//tensorflow/tools/pip_package:build_pip_package)'"""
28+
PIP_PACKAGE_QUERY_EXPRESSION = \
29+
'deps(//tensorflow/tools/pip_package:build_pip_package)'
3030

31-
PY_TEST_QUERY = """bazel query 'deps(\
31+
PY_TEST_QUERY_EXPRESSION = 'deps(\
3232
filter("^((?!benchmark).)*$",\
3333
kind(py_test,\
3434
//tensorflow/python/... \
3535
+ //tensorflow/contrib/... \
3636
- //tensorflow/contrib/tensorboard/... \
37-
- attr(tags, "manual|no_pip", //tensorflow/...))), 1)'"""
37+
- attr(tags, "manual|no_pip", //tensorflow/...))), 1)'
3838

3939
# Hard-coded blacklist of files if not included in pip package
4040
# TODO(amitpatankar): Clean up blacklist.
@@ -83,15 +83,15 @@ def main():
8383
"""
8484

8585
# pip_package_dependencies_list is the list of included files in pip packages
86-
pip_package_dependencies = subprocess.check_output(
87-
PIP_PACKAGE_QUERY, shell=True)
86+
pip_package_dependencies = subprocess.check_output([
87+
'bazel', 'query', PIP_PACKAGE_QUERY_EXPRESSION])
8888
pip_package_dependencies_list = pip_package_dependencies.strip().split("\n")
8989
print("Pip package superset size: %d" % len(pip_package_dependencies_list))
9090

9191
# tf_py_test_dependencies is the list of dependencies for all python
9292
# tests in tensorflow
93-
tf_py_test_dependencies = subprocess.check_output(
94-
PY_TEST_QUERY, shell=True)
93+
tf_py_test_dependencies = subprocess.check_output([
94+
'bazel', 'query', PY_TEST_QUERY_EXPRESSION])
9595
tf_py_test_dependencies_list = tf_py_test_dependencies.strip().split("\n")
9696
print("Pytest dependency subset size: %d" % len(tf_py_test_dependencies_list))
9797

@@ -124,9 +124,9 @@ def main():
124124
for missing_dependency in missing_dependencies:
125125
print("\nMissing dependency: %s " % missing_dependency)
126126
print("Affected Tests:")
127-
rdep_query = """bazel query 'rdeps(kind(py_test, \
128-
//tensorflow/python/...), %s)'""" % missing_dependency
129-
affected_tests = subprocess.check_output(rdep_query, shell=True)
127+
rdep_query = 'rdeps(kind(py_test, \
128+
//tensorflow/python/...), %s)' % missing_dependency
129+
affected_tests = subprocess.check_output(['bazel', 'query', rdep_query])
130130
affected_tests_list = affected_tests.split("\n")[:-2]
131131
print("\n".join(affected_tests_list))
132132

0 commit comments

Comments
 (0)