Path: blob/master/misc/direct/v1.5.2/launch_utils_org.py
3275 views
# this scripts installs necessary requirements and launches main program in webui.py1import re2import subprocess3import os4import sys5import importlib.util6import platform7import json8from functools import lru_cache910from modules import cmd_args, errors11from modules.paths_internal import script_path, extensions_dir12from modules import timer1314timer.startup_timer.record("start")1516args, _ = cmd_args.parser.parse_known_args()1718python = sys.executable19git = os.environ.get('GIT', "git")20index_url = os.environ.get('INDEX_URL', "")21dir_repos = "repositories"2223# Whether to default to printing command output24default_command_live = (os.environ.get('WEBUI_LAUNCH_LIVE_OUTPUT') == "1")2526if 'GRADIO_ANALYTICS_ENABLED' not in os.environ:27os.environ['GRADIO_ANALYTICS_ENABLED'] = 'False'282930def check_python_version():31is_windows = platform.system() == "Windows"32major = sys.version_info.major33minor = sys.version_info.minor34micro = sys.version_info.micro3536if is_windows:37supported_minors = [10]38else:39supported_minors = [7, 8, 9, 10, 11]4041if not (major == 3 and minor in supported_minors):42import modules.errors4344modules.errors.print_error_explanation(f"""45INCOMPATIBLE PYTHON VERSION4647This program is tested with 3.10.6 Python, but you have {major}.{minor}.{micro}.48If you encounter an error with "RuntimeError: Couldn't install torch." message,49or any other error regarding unsuccessful package (library) installation,50please downgrade (or upgrade) to the latest version of 3.10 Python51and delete current Python and "venv" folder in WebUI's directory.5253You can download 3.10 Python from here: https://www.python.org/downloads/release/python-3106/5455{"Alternatively, use a binary release of WebUI: https://github.com/AUTOMATIC1111/stable-diffusion-webui/releases" if is_windows else ""}5657Use --skip-python-version-check to suppress this warning.58""")596061@lru_cache()62def commit_hash():63try:64return subprocess.check_output([git, "rev-parse", "HEAD"], shell=False, encoding='utf8').strip()65except Exception:66return "<none>"676869@lru_cache()70def git_tag():71try:72return subprocess.check_output([git, "describe", "--tags"], shell=False, encoding='utf8').strip()73except Exception:74try:7576changelog_md = os.path.join(os.path.dirname(os.path.dirname(__file__)), "CHANGELOG.md")77with open(changelog_md, "r", encoding="utf-8") as file:78line = next((line.strip() for line in file if line.strip()), "<none>")79line = line.replace("## ", "")80return line81except Exception:82return "<none>"838485def run(command, desc=None, errdesc=None, custom_env=None, live: bool = default_command_live) -> str:86if desc is not None:87print(desc)8889run_kwargs = {90"args": command,91"shell": True,92"env": os.environ if custom_env is None else custom_env,93"encoding": 'utf8',94"errors": 'ignore',95}9697if not live:98run_kwargs["stdout"] = run_kwargs["stderr"] = subprocess.PIPE99100result = subprocess.run(**run_kwargs)101102if result.returncode != 0:103error_bits = [104f"{errdesc or 'Error running command'}.",105f"Command: {command}",106f"Error code: {result.returncode}",107]108if result.stdout:109error_bits.append(f"stdout: {result.stdout}")110if result.stderr:111error_bits.append(f"stderr: {result.stderr}")112raise RuntimeError("\n".join(error_bits))113114return (result.stdout or "")115116117def is_installed(package):118try:119spec = importlib.util.find_spec(package)120except ModuleNotFoundError:121return False122123return spec is not None124125126def repo_dir(name):127return os.path.join(script_path, dir_repos, name)128129130def run_pip(command, desc=None, live=default_command_live):131if args.skip_install:132return133134index_url_line = f' --index-url {index_url}' if index_url != '' else ''135return run(f'"{python}" -m pip {command} --prefer-binary{index_url_line}', desc=f"Installing {desc}", errdesc=f"Couldn't install {desc}", live=live)136137138def check_run_python(code: str) -> bool:139result = subprocess.run([python, "-c", code], capture_output=True, shell=False)140return result.returncode == 0141142143def git_clone(url, dir, name, commithash=None):144# TODO clone into temporary dir and move if successful145146if os.path.exists(dir):147if commithash is None:148return149150current_hash = run(f'"{git}" -C "{dir}" rev-parse HEAD', None, f"Couldn't determine {name}'s hash: {commithash}", live=False).strip()151if current_hash == commithash:152return153154run(f'"{git}" -C "{dir}" fetch', f"Fetching updates for {name}...", f"Couldn't fetch {name}")155run(f'"{git}" -C "{dir}" checkout {commithash}', f"Checking out commit for {name} with hash: {commithash}...", f"Couldn't checkout commit {commithash} for {name}", live=True)156return157158run(f'"{git}" clone "{url}" "{dir}"', f"Cloning {name} into {dir}...", f"Couldn't clone {name}", live=True)159160if commithash is not None:161run(f'"{git}" -C "{dir}" checkout {commithash}', None, "Couldn't checkout {name}'s hash: {commithash}")162163164def git_pull_recursive(dir):165for subdir, _, _ in os.walk(dir):166if os.path.exists(os.path.join(subdir, '.git')):167try:168output = subprocess.check_output([git, '-C', subdir, 'pull', '--autostash'])169print(f"Pulled changes for repository in '{subdir}':\n{output.decode('utf-8').strip()}\n")170except subprocess.CalledProcessError as e:171print(f"Couldn't perform 'git pull' on repository in '{subdir}':\n{e.output.decode('utf-8').strip()}\n")172173174def version_check(commit):175try:176import requests177commits = requests.get('https://api.github.com/repos/AUTOMATIC1111/stable-diffusion-webui/branches/master').json()178if commit != "<none>" and commits['commit']['sha'] != commit:179print("--------------------------------------------------------")180print("| You are not up to date with the most recent release. |")181print("| Consider running `git pull` to update. |")182print("--------------------------------------------------------")183elif commits['commit']['sha'] == commit:184print("You are up to date with the most recent release.")185else:186print("Not a git clone, can't perform version check.")187except Exception as e:188print("version check failed", e)189190191def run_extension_installer(extension_dir):192path_installer = os.path.join(extension_dir, "install.py")193if not os.path.isfile(path_installer):194return195196try:197env = os.environ.copy()198env['PYTHONPATH'] = f"{os.path.abspath('.')}{os.pathsep}{env.get('PYTHONPATH', '')}"199200print(run(f'"{python}" "{path_installer}"', errdesc=f"Error running install.py for extension {extension_dir}", custom_env=env))201except Exception as e:202errors.report(str(e))203204205def list_extensions(settings_file):206settings = {}207208try:209if os.path.isfile(settings_file):210with open(settings_file, "r", encoding="utf8") as file:211settings = json.load(file)212except Exception:213errors.report("Could not load settings", exc_info=True)214215disabled_extensions = set(settings.get('disabled_extensions', []))216disable_all_extensions = settings.get('disable_all_extensions', 'none')217218if disable_all_extensions != 'none':219return []220221return [x for x in os.listdir(extensions_dir) if x not in disabled_extensions]222223224def run_extensions_installers(settings_file):225if not os.path.isdir(extensions_dir):226return227228for dirname_extension in list_extensions(settings_file):229run_extension_installer(os.path.join(extensions_dir, dirname_extension))230231232re_requirement = re.compile(r"\s*([-_a-zA-Z0-9]+)\s*(?:==\s*([-+_.a-zA-Z0-9]+))?\s*")233234235def requirements_met(requirements_file):236"""237Does a simple parse of a requirements.txt file to determine if all rerqirements in it238are already installed. Returns True if so, False if not installed or parsing fails.239"""240241import importlib.metadata242import packaging.version243244with open(requirements_file, "r", encoding="utf8") as file:245for line in file:246if line.strip() == "":247continue248249m = re.match(re_requirement, line)250if m is None:251return False252253package = m.group(1).strip()254version_required = (m.group(2) or "").strip()255256if version_required == "":257continue258259try:260version_installed = importlib.metadata.version(package)261except Exception:262return False263264if packaging.version.parse(version_required) != packaging.version.parse(version_installed):265return False266267return True268269270def prepare_environment():271torch_index_url = os.environ.get('TORCH_INDEX_URL', "https://download.pytorch.org/whl/cu118")272torch_command = os.environ.get('TORCH_COMMAND', f"pip install torch==2.0.1 torchvision==0.15.2 --extra-index-url {torch_index_url}")273requirements_file = os.environ.get('REQS_FILE', "requirements_versions.txt")274275xformers_package = os.environ.get('XFORMERS_PACKAGE', 'xformers==0.0.20')276gfpgan_package = os.environ.get('GFPGAN_PACKAGE', "https://github.com/TencentARC/GFPGAN/archive/8d2447a2d918f8eba5a4a01463fd48e45126a379.zip")277clip_package = os.environ.get('CLIP_PACKAGE', "https://github.com/openai/CLIP/archive/d50d76daa670286dd6cacf3bcd80b5e4823fc8e1.zip")278openclip_package = os.environ.get('OPENCLIP_PACKAGE', "https://github.com/mlfoundations/open_clip/archive/bb6e834e9c70d9c27d0dc3ecedeebeaeb1ffad6b.zip")279280stable_diffusion_repo = os.environ.get('STABLE_DIFFUSION_REPO', "https://github.com/Stability-AI/stablediffusion.git")281stable_diffusion_xl_repo = os.environ.get('STABLE_DIFFUSION_XL_REPO', "https://github.com/Stability-AI/generative-models.git")282k_diffusion_repo = os.environ.get('K_DIFFUSION_REPO', 'https://github.com/crowsonkb/k-diffusion.git')283codeformer_repo = os.environ.get('CODEFORMER_REPO', 'https://github.com/sczhou/CodeFormer.git')284blip_repo = os.environ.get('BLIP_REPO', 'https://github.com/salesforce/BLIP.git')285286stable_diffusion_commit_hash = os.environ.get('STABLE_DIFFUSION_COMMIT_HASH', "cf1d67a6fd5ea1aa600c4df58e5b47da45f6bdbf")287stable_diffusion_xl_commit_hash = os.environ.get('STABLE_DIFFUSION_XL_COMMIT_HASH', "5c10deee76adad0032b412294130090932317a87")288k_diffusion_commit_hash = os.environ.get('K_DIFFUSION_COMMIT_HASH', "c9fe758757e022f05ca5a53fa8fac28889e4f1cf")289codeformer_commit_hash = os.environ.get('CODEFORMER_COMMIT_HASH', "c5b4593074ba6214284d6acd5f1719b6c5d739af")290blip_commit_hash = os.environ.get('BLIP_COMMIT_HASH', "48211a1594f1321b00f14c9f7a5b4813144b2fb9")291292try:293# the existance of this file is a signal to webui.sh/bat that webui needs to be restarted when it stops execution294os.remove(os.path.join(script_path, "tmp", "restart"))295os.environ.setdefault('SD_WEBUI_RESTARTING', '1')296except OSError:297pass298299if not args.skip_python_version_check:300check_python_version()301302commit = commit_hash()303tag = git_tag()304305print(f"Python {sys.version}")306print(f"Version: {tag}")307print(f"Commit hash: {commit}")308309if args.reinstall_torch or not is_installed("torch") or not is_installed("torchvision"):310run(f'"{python}" -m {torch_command}', "Installing torch and torchvision", "Couldn't install torch", live=True)311312if not args.skip_torch_cuda_test and not check_run_python("import torch; assert torch.cuda.is_available()"):313raise RuntimeError(314'Torch is not able to use GPU; '315'add --skip-torch-cuda-test to COMMANDLINE_ARGS variable to disable this check'316)317318if not is_installed("gfpgan"):319run_pip(f"install {gfpgan_package}", "gfpgan")320321if not is_installed("clip"):322run_pip(f"install {clip_package}", "clip")323324if not is_installed("open_clip"):325run_pip(f"install {openclip_package}", "open_clip")326327if (not is_installed("xformers") or args.reinstall_xformers) and args.xformers:328if platform.system() == "Windows":329if platform.python_version().startswith("3.10"):330run_pip(f"install -U -I --no-deps {xformers_package}", "xformers", live=True)331else:332print("Installation of xformers is not supported in this version of Python.")333print("You can also check this and build manually: https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Xformers#building-xformers-on-windows-by-duckness")334if not is_installed("xformers"):335exit(0)336elif platform.system() == "Linux":337run_pip(f"install -U -I --no-deps {xformers_package}", "xformers")338339if not is_installed("ngrok") and args.ngrok:340run_pip("install ngrok", "ngrok")341342os.makedirs(os.path.join(script_path, dir_repos), exist_ok=True)343344git_clone(stable_diffusion_repo, repo_dir('stable-diffusion-stability-ai'), "Stable Diffusion", stable_diffusion_commit_hash)345git_clone(stable_diffusion_xl_repo, repo_dir('generative-models'), "Stable Diffusion XL", stable_diffusion_xl_commit_hash)346git_clone(k_diffusion_repo, repo_dir('k-diffusion'), "K-diffusion", k_diffusion_commit_hash)347git_clone(codeformer_repo, repo_dir('CodeFormer'), "CodeFormer", codeformer_commit_hash)348git_clone(blip_repo, repo_dir('BLIP'), "BLIP", blip_commit_hash)349350if not is_installed("lpips"):351run_pip(f"install -r \"{os.path.join(repo_dir('CodeFormer'), 'requirements.txt')}\"", "requirements for CodeFormer")352353if not os.path.isfile(requirements_file):354requirements_file = os.path.join(script_path, requirements_file)355356if not requirements_met(requirements_file):357run_pip(f"install -r \"{requirements_file}\"", "requirements")358359run_extensions_installers(settings_file=args.ui_settings_file)360361if args.update_check:362version_check(commit)363364if args.update_all_extensions:365git_pull_recursive(extensions_dir)366367if "--exit" in sys.argv:368print("Exiting because of --exit argument")369exit(0)370371372373def configure_for_tests():374if "--api" not in sys.argv:375sys.argv.append("--api")376if "--ckpt" not in sys.argv:377sys.argv.append("--ckpt")378sys.argv.append(os.path.join(script_path, "test/test_files/empty.pt"))379if "--skip-torch-cuda-test" not in sys.argv:380sys.argv.append("--skip-torch-cuda-test")381if "--disable-nan-check" not in sys.argv:382sys.argv.append("--disable-nan-check")383384os.environ['COMMANDLINE_ARGS'] = ""385386387def start():388print(f"Launching {'API server' if '--nowebui' in sys.argv else 'Web UI'} with arguments: {' '.join(sys.argv[1:])}")389import webui390if '--nowebui' in sys.argv:391webui.api_only()392else:393webui.webui()394395396