kopia lustrzana https://github.com/OpenDroneMap/ODM
176 wiersze
4.9 KiB
Python
176 wiersze
4.9 KiB
Python
import os
|
|
import errno
|
|
import json
|
|
import datetime
|
|
import sys
|
|
import subprocess
|
|
import string
|
|
import signal
|
|
import io
|
|
import shutil
|
|
from collections import deque
|
|
|
|
from opendm import context
|
|
from opendm import log
|
|
|
|
class SubprocessException(Exception):
|
|
def __init__(self, msg, errorCode):
|
|
super().__init__(msg)
|
|
self.errorCode = errorCode
|
|
|
|
class ExitException(Exception):
|
|
pass
|
|
|
|
def get_ccd_widths():
|
|
"""Return the CCD Width of the camera listed in the JSON defs file."""
|
|
with open(context.ccd_widths_path) as f:
|
|
sensor_data = json.loads(f.read())
|
|
return dict(zip(map(string.lower, sensor_data.keys()), sensor_data.values()))
|
|
|
|
running_subprocesses = []
|
|
cleanup_callbacks = []
|
|
|
|
def add_cleanup_callback(func):
|
|
global cleanup_callbacks
|
|
cleanup_callbacks.append(func)
|
|
|
|
def remove_cleanup_callback(func):
|
|
global cleanup_callbacks
|
|
|
|
try:
|
|
cleanup_callbacks.remove(func)
|
|
except ValueError as e:
|
|
log.ODM_EXCEPTION("Tried to remove %s from cleanup_callbacks but got: %s" % (str(func), str(e)))
|
|
|
|
def exit_gracefully():
|
|
global running_subprocesses
|
|
global cleanup_callbacks
|
|
|
|
log.ODM_WARNING("Caught TERM/INT signal, attempting to exit gracefully...")
|
|
|
|
for cb in cleanup_callbacks:
|
|
cb()
|
|
|
|
for sp in running_subprocesses:
|
|
log.ODM_WARNING("Sending TERM signal to PID %s..." % sp.pid)
|
|
if sys.platform == 'win32':
|
|
os.kill(sp.pid, signal.CTRL_C_EVENT)
|
|
else:
|
|
os.killpg(os.getpgid(sp.pid), signal.SIGTERM)
|
|
|
|
os._exit(1)
|
|
|
|
def sighandler(signum, frame):
|
|
exit_gracefully()
|
|
|
|
signal.signal(signal.SIGINT, sighandler)
|
|
signal.signal(signal.SIGTERM, sighandler)
|
|
|
|
def run(cmd, env_paths=[context.superbuild_bin_path], env_vars={}, packages_paths=context.python_packages_paths, quiet=False):
|
|
"""Run a system command"""
|
|
global running_subprocesses
|
|
|
|
if not quiet:
|
|
log.ODM_INFO('running %s' % cmd)
|
|
env = os.environ.copy()
|
|
|
|
sep = ":"
|
|
if sys.platform == 'win32':
|
|
sep = ";"
|
|
|
|
if len(env_paths) > 0:
|
|
env["PATH"] = env["PATH"] + sep + sep.join(env_paths)
|
|
|
|
if len(packages_paths) > 0:
|
|
env["PYTHONPATH"] = env.get("PYTHONPATH", "") + sep + sep.join(packages_paths)
|
|
if sys.platform == 'darwin':
|
|
# Propagate DYLD_LIBRARY_PATH
|
|
cmd = "export DYLD_LIBRARY_PATH=\"%s\" && %s" % (env.get("DYLD_LIBRARY_PATH", ""), cmd)
|
|
|
|
for k in env_vars:
|
|
env[k] = str(env_vars[k])
|
|
|
|
p = subprocess.Popen(cmd, shell=True, env=env, start_new_session=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
running_subprocesses.append(p)
|
|
lines = deque()
|
|
for line in io.TextIOWrapper(p.stdout):
|
|
print(line, end="")
|
|
|
|
lines.append(line.strip())
|
|
if len(lines) == 11:
|
|
lines.popleft()
|
|
|
|
retcode = p.wait()
|
|
|
|
if not quiet:
|
|
log.logger.log_json_process(cmd, retcode, list(lines))
|
|
|
|
running_subprocesses.remove(p)
|
|
if retcode < 0:
|
|
raise SubprocessException("Child was terminated by signal {}".format(-retcode), -retcode)
|
|
elif retcode > 0:
|
|
raise SubprocessException("Child returned {}".format(retcode), retcode)
|
|
|
|
|
|
def now():
|
|
"""Return the current time"""
|
|
return datetime.datetime.now().strftime('%a %b %d %H:%M:%S %Z %Y')
|
|
|
|
|
|
def now_raw():
|
|
return datetime.datetime.now()
|
|
|
|
|
|
def benchmark(start, benchmarking_file, process):
|
|
"""
|
|
runs a benchmark with a start datetime object
|
|
:return: the running time (delta)
|
|
"""
|
|
# Write to benchmark file
|
|
delta = (datetime.datetime.now() - start).total_seconds()
|
|
with open(benchmarking_file, 'a') as b:
|
|
b.write('%s runtime: %s seconds\n' % (process, delta))
|
|
|
|
def mkdir_p(path):
|
|
"""Make a directory including parent directories.
|
|
"""
|
|
try:
|
|
os.makedirs(path)
|
|
except os.error as exc:
|
|
if exc.errno != errno.EEXIST or not os.path.isdir(path):
|
|
raise
|
|
|
|
# Python2 shutil.which
|
|
def which(program):
|
|
path=os.getenv('PATH')
|
|
for p in path.split(os.path.pathsep):
|
|
p=os.path.join(p,program)
|
|
if os.path.exists(p) and os.access(p,os.X_OK):
|
|
return p
|
|
|
|
def link_file(src, dst):
|
|
if os.path.isdir(dst):
|
|
dst = os.path.join(dst, os.path.basename(src))
|
|
|
|
if not os.path.isfile(dst):
|
|
if sys.platform == 'win32':
|
|
os.link(src, dst)
|
|
else:
|
|
os.symlink(os.path.relpath(os.path.abspath(src), os.path.dirname(os.path.abspath(dst))), dst)
|
|
|
|
def move_files(src, dst):
|
|
if not os.path.isdir(dst):
|
|
raise IOError("Not a directory: %s" % dst)
|
|
|
|
for f in os.listdir(src):
|
|
if os.path.isfile(os.path.join(src, f)):
|
|
shutil.move(os.path.join(src, f), dst)
|
|
|
|
def delete_files(folder, exclude=()):
|
|
if not os.path.isdir(folder):
|
|
return
|
|
|
|
for f in os.listdir(folder):
|
|
if os.path.isfile(os.path.join(folder, f)):
|
|
if not exclude or not f.endswith(exclude):
|
|
os.unlink(os.path.join(folder, f)) |