Subprocess improvements (#10973)
* Use list-form arguments for subprocess.run calls where possible Augments #10944 * Deduplicate curl code * Avoid eval() to parse integer --------- Signed-off-by: Glenn Jocher <glenn.jocher@ultralytics.com> Co-authored-by: Glenn Jocher <glenn.jocher@ultralytics.com>
This commit is contained in:
1 parent
1a2eb532ce
commit
a2de5c5bf6
8 files changed
+68
-24
No files matched your search
+1
-1
@@ -78,7 +78,7 @@ def train(opt, device):
|
|||||||
LOGGER.info(f'\nDataset not found ⚠️, missing path {data_dir}, attempting download...')
|
LOGGER.info(f'\nDataset not found ⚠️, missing path {data_dir}, attempting download...')
|
||||||
t = time.time()
|
t = time.time()
|
||||||
if str(data) == 'imagenet':
|
if str(data) == 'imagenet':
|
||||||
subprocess.run(f"bash {ROOT / 'data/scripts/get_imagenet.sh'}", shell=True, check=True)
|
subprocess.run(["bash", str(ROOT / 'data/scripts/get_imagenet.sh')], shell=True, check=True)
|
||||||
else:
|
else:
|
||||||
url = f'https://github.com/ultralytics/yolov5/releases/download/v1.0/{data}.zip'
|
url = f'https://github.com/ultralytics/yolov5/releases/download/v1.0/{data}.zip'
|
||||||
download(url, dir=data_dir.parent)
|
download(url, dir=data_dir.parent)
|
||||||
|
|||||||
@@ -194,8 +194,15 @@ def export_openvino(file, metadata, half, prefix=colorstr('OpenVINO:')):
|
|||||||
LOGGER.info(f'\n{prefix} starting export with openvino {ie.__version__}...')
|
LOGGER.info(f'\n{prefix} starting export with openvino {ie.__version__}...')
|
||||||
f = str(file).replace('.pt', f'_openvino_model{os.sep}')
|
f = str(file).replace('.pt', f'_openvino_model{os.sep}')
|
||||||
|
|
||||||
cmd = f"mo --input_model {file.with_suffix('.onnx')} --output_dir {f} --data_type {'FP16' if half else 'FP32'}"
|
args = [
|
||||||
subprocess.run(cmd.split(), check=True, env=os.environ) # export
|
"mo",
|
||||||
|
"--input_model",
|
||||||
|
str(file.with_suffix('.onnx')),
|
||||||
|
"--output_dir",
|
||||||
|
f,
|
||||||
|
"--data_type",
|
||||||
|
("FP16" if half else "FP32"),]
|
||||||
|
subprocess.run(args, check=True, env=os.environ) # export
|
||||||
yaml_save(Path(f) / file.with_suffix('.yaml').name, metadata) # add metadata.yaml
|
yaml_save(Path(f) / file.with_suffix('.yaml').name, metadata) # add metadata.yaml
|
||||||
return f, None
|
return f, None
|
||||||
|
|
||||||
@@ -420,8 +427,15 @@ def export_edgetpu(file, prefix=colorstr('Edge TPU:')):
|
|||||||
f = str(file).replace('.pt', '-int8_edgetpu.tflite') # Edge TPU model
|
f = str(file).replace('.pt', '-int8_edgetpu.tflite') # Edge TPU model
|
||||||
f_tfl = str(file).replace('.pt', '-int8.tflite') # TFLite model
|
f_tfl = str(file).replace('.pt', '-int8.tflite') # TFLite model
|
||||||
|
|
||||||
cmd = f"edgetpu_compiler -s -d -k 10 --out_dir {file.parent} {f_tfl}"
|
subprocess.run([
|
||||||
subprocess.run(cmd.split(), check=True)
|
'edgetpu_compiler',
|
||||||
|
'-s',
|
||||||
|
'-d',
|
||||||
|
'-k',
|
||||||
|
'10',
|
||||||
|
'--out_dir',
|
||||||
|
str(file.parent),
|
||||||
|
f_tfl,], check=True)
|
||||||
return f, None
|
return f, None
|
||||||
|
|
||||||
|
|
||||||
@@ -436,11 +450,14 @@ def export_tfjs(file, int8, prefix=colorstr('TensorFlow.js:')):
|
|||||||
f_pb = file.with_suffix('.pb') # *.pb path
|
f_pb = file.with_suffix('.pb') # *.pb path
|
||||||
f_json = f'{f}/model.json' # *.json path
|
f_json = f'{f}/model.json' # *.json path
|
||||||
|
|
||||||
int8_export = ' --quantize_uint8 ' if int8 else ''
|
args = [
|
||||||
|
'tensorflowjs_converter',
|
||||||
cmd = f'tensorflowjs_converter --input_format=tf_frozen_model {int8_export}' \
|
'--input_format=tf_frozen_model',
|
||||||
f'--output_node_names=Identity,Identity_1,Identity_2,Identity_3 {f_pb} {f}'
|
'--quantize_uint8' if int8 else '',
|
||||||
subprocess.run(cmd.split())
|
'--output_node_names=Identity,Identity_1,Identity_2,Identity_3',
|
||||||
|
str(f_pb),
|
||||||
|
str(f),]
|
||||||
|
subprocess.run([arg for arg in args if arg], check=True)
|
||||||
|
|
||||||
json = Path(f_json).read_text()
|
json = Path(f_json).read_text()
|
||||||
with open(f_json, 'w') as j: # sort JSON Identity_* in ascending order
|
with open(f_json, 'w') as j: # sort JSON Identity_* in ascending order
|
||||||
|
|||||||
+6
-2
@@ -598,8 +598,12 @@ def main(opt, callbacks=Callbacks()):
|
|||||||
# ei = [isinstance(x, (int, float)) for x in hyp.values()] # evolvable indices
|
# ei = [isinstance(x, (int, float)) for x in hyp.values()] # evolvable indices
|
||||||
evolve_yaml, evolve_csv = save_dir / 'hyp_evolve.yaml', save_dir / 'evolve.csv'
|
evolve_yaml, evolve_csv = save_dir / 'hyp_evolve.yaml', save_dir / 'evolve.csv'
|
||||||
if opt.bucket:
|
if opt.bucket:
|
||||||
subprocess.run(
|
# download evolve.csv if exists
|
||||||
f'gsutil cp gs://{opt.bucket}/evolve.csv {evolve_csv}'.split()) # download evolve.csv if exists
|
subprocess.run([
|
||||||
|
'gsutil',
|
||||||
|
'cp',
|
||||||
|
f'gs://{opt.bucket}/evolve.csv',
|
||||||
|
str(evolve_csv),])
|
||||||
|
|
||||||
for _ in range(opt.evolve): # generations to evolve
|
for _ in range(opt.evolve): # generations to evolve
|
||||||
if evolve_csv.exists(): # if evolve.csv exists: select best hyps and mutate
|
if evolve_csv.exists(): # if evolve.csv exists: select best hyps and mutate
|
||||||
|
|||||||
+1
-1
@@ -462,7 +462,7 @@ def main(opt):
|
|||||||
r, _, t = run(**vars(opt), plots=False)
|
r, _, t = run(**vars(opt), plots=False)
|
||||||
y.append(r + t) # results and times
|
y.append(r + t) # results and times
|
||||||
np.savetxt(f, y, fmt='%10.4g') # save
|
np.savetxt(f, y, fmt='%10.4g') # save
|
||||||
subprocess.run('zip -r study.zip study_*.txt'.split())
|
subprocess.run(['zip', '-r', 'study.zip', 'study_*.txt'])
|
||||||
plot_val_study(x=x) # plot
|
plot_val_study(x=x) # plot
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(f'--task {opt.task} not in ("train", "val", "test", "speed", "study")')
|
raise NotImplementedError(f'--task {opt.task} not in ("train", "val", "test", "speed", "study")')
|
||||||
|
|||||||
@@ -572,8 +572,12 @@ def main(opt, callbacks=Callbacks()):
|
|||||||
# ei = [isinstance(x, (int, float)) for x in hyp.values()] # evolvable indices
|
# ei = [isinstance(x, (int, float)) for x in hyp.values()] # evolvable indices
|
||||||
evolve_yaml, evolve_csv = save_dir / 'hyp_evolve.yaml', save_dir / 'evolve.csv'
|
evolve_yaml, evolve_csv = save_dir / 'hyp_evolve.yaml', save_dir / 'evolve.csv'
|
||||||
if opt.bucket:
|
if opt.bucket:
|
||||||
subprocess.run(
|
# download evolve.csv if exists
|
||||||
f'gsutil cp gs://{opt.bucket}/evolve.csv {evolve_csv}'.split()) # download evolve.csv if exists
|
subprocess.run([
|
||||||
|
'gsutil',
|
||||||
|
'cp',
|
||||||
|
f'gs://{opt.bucket}/evolve.csv',
|
||||||
|
str(evolve_csv),])
|
||||||
|
|
||||||
for _ in range(opt.evolve): # generations to evolve
|
for _ in range(opt.evolve): # generations to evolve
|
||||||
if evolve_csv.exists(): # if evolve.csv exists: select best hyps and mutate
|
if evolve_csv.exists(): # if evolve.csv exists: select best hyps and mutate
|
||||||
|
|||||||
+25
-4
@@ -26,8 +26,10 @@ def is_url(url, check=True):
|
|||||||
|
|
||||||
def gsutil_getsize(url=''):
|
def gsutil_getsize(url=''):
|
||||||
# gs://bucket/file size https://cloud.google.com/storage/docs/gsutil/commands/du
|
# gs://bucket/file size https://cloud.google.com/storage/docs/gsutil/commands/du
|
||||||
s = subprocess.check_output(f'gsutil du {url}', shell=True).decode('utf-8')
|
output = subprocess.check_output(['gsutil', 'du', url], shell=True, encoding='utf-8')
|
||||||
return eval(s.split(' ')[0]) if len(s) else 0 # bytes
|
if output:
|
||||||
|
return int(output.split()[0])
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def url_getsize(url='https://ultralytics.com/images/bus.jpg'):
|
def url_getsize(url='https://ultralytics.com/images/bus.jpg'):
|
||||||
@@ -36,6 +38,25 @@ def url_getsize(url='https://ultralytics.com/images/bus.jpg'):
|
|||||||
return int(response.headers.get('content-length', -1))
|
return int(response.headers.get('content-length', -1))
|
||||||
|
|
||||||
|
|
||||||
|
def curl_download(url, filename, *, silent: bool = False) -> bool:
|
||||||
|
"""
|
||||||
|
Download a file from a url to a filename using curl.
|
||||||
|
"""
|
||||||
|
silent_option = 'sS' if silent else '' # silent
|
||||||
|
proc = subprocess.run([
|
||||||
|
'curl',
|
||||||
|
'-#',
|
||||||
|
f'-{silent_option}L',
|
||||||
|
url,
|
||||||
|
'--output',
|
||||||
|
filename,
|
||||||
|
'--retry',
|
||||||
|
'9',
|
||||||
|
'-C',
|
||||||
|
'-',])
|
||||||
|
return proc.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
def safe_download(file, url, url2=None, min_bytes=1E0, error_msg=''):
|
def safe_download(file, url, url2=None, min_bytes=1E0, error_msg=''):
|
||||||
# Attempts to download file from url or url2, checks and removes incomplete downloads < min_bytes
|
# Attempts to download file from url or url2, checks and removes incomplete downloads < min_bytes
|
||||||
from utils.general import LOGGER
|
from utils.general import LOGGER
|
||||||
@@ -50,8 +71,8 @@ def safe_download(file, url, url2=None, min_bytes=1E0, error_msg=''):
|
|||||||
if file.exists():
|
if file.exists():
|
||||||
file.unlink() # remove partial downloads
|
file.unlink() # remove partial downloads
|
||||||
LOGGER.info(f'ERROR: {e}\nRe-attempting {url2 or url} to {file}...')
|
LOGGER.info(f'ERROR: {e}\nRe-attempting {url2 or url} to {file}...')
|
||||||
subprocess.run(
|
# curl download, retry and resume on fail
|
||||||
f"curl -# -L '{url2 or url}' -o '{file}' --retry 3 -C -".split()) # curl download, retry and resume on fail
|
curl_download(url2 or url, file)
|
||||||
finally:
|
finally:
|
||||||
if not file.exists() or file.stat().st_size < min_bytes: # check
|
if not file.exists() or file.stat().st_size < min_bytes: # check
|
||||||
if file.exists():
|
if file.exists():
|
||||||
|
|||||||
+2
-4
@@ -38,7 +38,7 @@ import torchvision
|
|||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from utils import TryExcept, emojis
|
from utils import TryExcept, emojis
|
||||||
from utils.downloads import gsutil_getsize
|
from utils.downloads import gsutil_getsize, curl_download
|
||||||
from utils.metrics import box_iou, fitness
|
from utils.metrics import box_iou, fitness
|
||||||
|
|
||||||
FILE = Path(__file__).resolve()
|
FILE = Path(__file__).resolve()
|
||||||
@@ -630,9 +630,7 @@ def download(url, dir='.', unzip=True, delete=True, curl=False, threads=1, retry
|
|||||||
LOGGER.info(f'Downloading {url} to {f}...')
|
LOGGER.info(f'Downloading {url} to {f}...')
|
||||||
for i in range(retry + 1):
|
for i in range(retry + 1):
|
||||||
if curl:
|
if curl:
|
||||||
s = 'sS' if threads > 1 else '' # silent
|
success = curl_download(url, f, silent=(threads > 1))
|
||||||
proc = subprocess.run(f'curl -# -{s}L "{url}" -o "{f}" --retry 9 -C -'.split())
|
|
||||||
success = proc.returncode == 0
|
|
||||||
else:
|
else:
|
||||||
torch.hub.download_url_to_file(url, f, progress=threads == 1) # torch download
|
torch.hub.download_url_to_file(url, f, progress=threads == 1) # torch download
|
||||||
success = f.is_file()
|
success = f.is_file()
|
||||||
|
|||||||
@@ -398,7 +398,7 @@ def main(opt):
|
|||||||
r, _, t = run(**vars(opt), plots=False)
|
r, _, t = run(**vars(opt), plots=False)
|
||||||
y.append(r + t) # results and times
|
y.append(r + t) # results and times
|
||||||
np.savetxt(f, y, fmt='%10.4g') # save
|
np.savetxt(f, y, fmt='%10.4g') # save
|
||||||
subprocess.run('zip -r study.zip study_*.txt'.split())
|
subprocess.run(['zip', '-r', 'study.zip', 'study_*.txt'])
|
||||||
plot_val_study(x=x) # plot
|
plot_val_study(x=x) # plot
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError(f'--task {opt.task} not in ("train", "val", "test", "speed", "study")')
|
raise NotImplementedError(f'--task {opt.task} not in ("train", "val", "test", "speed", "study")')
|
||||||
|
|||||||
Reference in new issue
Block a user