From 2ece9782e4696b4e35a900b5bb1e061ab95ef8b6 Mon Sep 17 00:00:00 2001
From: Vladimir Mandic
Date: Fri, 14 Apr 2023 09:57:53 -0400
Subject: [PATCH] handle duplicate extensions and redo exception handler
---
TODO.md | 7 ++
extensions-builtin/sd-extension-system-info | 2 +-
extensions-builtin/sd-webui-controlnet | 2 +-
.../stable-diffusion-webui-images-browser | 2 +-
modules/api/api.py | 17 +----
modules/call_queue.py | 16 +----
modules/codeformer_model.py | 7 +-
modules/errors.py | 17 ++++-
modules/extensions.py | 21 +++---
modules/gfpgan_model.py | 7 +-
modules/hypernetworks/hypernetwork.py | 11 ++--
modules/images.py | 10 ++-
modules/interrogate.py | 5 +-
modules/localization.py | 5 +-
modules/lora | 2 +-
modules/paths.py | 9 +--
modules/realesrgan_model.py | 9 ++-
modules/safe.py | 14 +---
modules/script_callbacks.py | 66 +++++++++----------
modules/script_loading.py | 6 +-
modules/scripts.py | 52 ++++++---------
modules/sd_models.py | 7 +-
modules/shared.py | 27 ++------
.../textual_inversion/textual_inversion.py | 11 ++--
modules/ui.py | 10 ++-
modules/ui_extensions.py | 10 ++-
scripts/prompts_from_file.py | 7 +-
setup.py | 14 ++--
28 files changed, 161 insertions(+), 212 deletions(-)
diff --git a/TODO.md b/TODO.md
index 53ede1a74..07a86e948 100644
--- a/TODO.md
+++ b/TODO.md
@@ -15,6 +15,13 @@ Stuff to be fixed...
- Support mupliple folders for models
- Add compatibility for extensions using removed `shared.cmd_opts`
- Revisit `torch.compile`
+- Ask to download default model
+- Support UI restart on-the-fly
+- Re-add seed buttons
+- Stream-load as option
+- Verify env variables
+- Configurable LORA directory
+- Dont spawn extensions installer
## Integration
diff --git a/extensions-builtin/sd-extension-system-info b/extensions-builtin/sd-extension-system-info
index f3499ddd8..be495d02e 160000
--- a/extensions-builtin/sd-extension-system-info
+++ b/extensions-builtin/sd-extension-system-info
@@ -1 +1 @@
-Subproject commit f3499ddd8bebd4a743b8f63e58cce934b04cb8d2
+Subproject commit be495d02ef8eac8c16542080426ba74c3a42839e
diff --git a/extensions-builtin/sd-webui-controlnet b/extensions-builtin/sd-webui-controlnet
index 0f549888f..e5b565e27 160000
--- a/extensions-builtin/sd-webui-controlnet
+++ b/extensions-builtin/sd-webui-controlnet
@@ -1 +1 @@
-Subproject commit 0f549888fd49aea48a4a5049f75c2e87ad3affad
+Subproject commit e5b565e27f0fdda34d1ccbdbe4d6ab07d3d2fc67
diff --git a/extensions-builtin/stable-diffusion-webui-images-browser b/extensions-builtin/stable-diffusion-webui-images-browser
index 57040c311..0029d95a5 160000
--- a/extensions-builtin/stable-diffusion-webui-images-browser
+++ b/extensions-builtin/stable-diffusion-webui-images-browser
@@ -1 +1 @@
-Subproject commit 57040c311fc540bca9ca9d5ada2a9dd521f03f95
+Subproject commit 0029d95a5f720b387c530e916a9e166277aa66e2
diff --git a/modules/api/api.py b/modules/api/api.py
index a5a864e25..cb4cee07f 100644
--- a/modules/api/api.py
+++ b/modules/api/api.py
@@ -14,8 +14,7 @@ from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
from secrets import compare_digest
-import modules.shared as shared
-from modules import sd_samplers, deepbooru, sd_hijack, images, scripts, ui, postprocessing
+from modules import shared, errors, sd_samplers, deepbooru, sd_hijack, images, scripts, ui, postprocessing
from modules.api.models import *
from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img, process_images
from modules.textual_inversion.textual_inversion import create_embedding, train_embedding
@@ -94,15 +93,6 @@ def encode_pil_to_base64(image):
return base64.b64encode(bytes_data)
def api_middleware(app: FastAPI):
- rich_available = True
- try:
- import anyio # importing just so it can be placed on silent list
- import starlette # importing just so it can be placed on silent list
- from rich.console import Console
- console = Console()
- except:
- import traceback
- rich_available = False
@app.middleware("http")
async def log_and_time(req: Request, call_next):
@@ -133,10 +123,7 @@ def api_middleware(app: FastAPI):
}
print(f"API error: {request.method}: {request.url} {err}")
if not isinstance(e, HTTPException): # do not print backtrace on known httpexceptions
- if rich_available:
- console.print_exception(show_locals=False, max_frames=2, extra_lines=1, suppress=[anyio, starlette], word_wrap=False, width=min([console.width, 200]))
- else:
- traceback.print_exc()
+ errors.display(e, 'http api')
return JSONResponse(status_code=vars(e).get('status_code', 500), content=jsonable_encoder(err))
@app.middleware("http")
diff --git a/modules/call_queue.py b/modules/call_queue.py
index 17f247567..833a0bb2f 100644
--- a/modules/call_queue.py
+++ b/modules/call_queue.py
@@ -1,10 +1,9 @@
import html
-import sys
import threading
import time
import cProfile, pstats, io
-from modules import shared, progress
+from modules import shared, progress, errors
queue_lock = threading.Lock()
@@ -65,22 +64,11 @@ def wrap_gradio_call(func, extra_outputs=None, add_stats=False):
ps.print_stats(15)
print('Profile:', s.getvalue())
except Exception as e:
- # When printing out our debug argument list, do not print out more than a MB of text
- max_debug_str_len = 131072 # (1024*1024)/8
-
- print("Error completing request", file=sys.stderr)
- argStr = f"Arguments: {str(args)} {str(kwargs)}"
- print(argStr[:max_debug_str_len], file=sys.stderr)
- if len(argStr) > max_debug_str_len:
- print(f"(Argument list truncated at {max_debug_str_len}/{len(argStr)} characters)", file=sys.stderr)
-
- shared.exception()
+ errors.display(e, 'gradio call')
shared.state.job = ""
shared.state.job_count = 0
-
if extra_outputs_array is None:
extra_outputs_array = [None, '']
-
res = extra_outputs_array + [f"{html.escape(type(e).__name__+': '+str(e))}
"]
shared.state.skipped = False
diff --git a/modules/codeformer_model.py b/modules/codeformer_model.py
index e9c668b61..c33f12773 100644
--- a/modules/codeformer_model.py
+++ b/modules/codeformer_model.py
@@ -6,7 +6,7 @@ import torch
import modules.face_restoration
import modules.shared
-from modules import shared, devices, modelloader
+from modules import shared, devices, modelloader, errors
from modules.paths import models_path
# codeformer people made a choice to include modified basicsr library to their project which makes
@@ -135,8 +135,7 @@ def setup_model(dirname):
codeformer = FaceRestorerCodeFormer(dirname)
shared.face_restorers.append(codeformer)
- except Exception:
- print("Error setting up CodeFormer:", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, 'codeformer')
# sys.path = stored_sys_path
diff --git a/modules/errors.py b/modules/errors.py
index 017269174..dba20b6e4 100644
--- a/modules/errors.py
+++ b/modules/errors.py
@@ -1,7 +1,15 @@
import sys
-import traceback
+import anyio
+import starlette
+import gradio
+from rich import print
from rich.console import Console
+from rich.pretty import install as pretty_install
+from rich.traceback import install as traceback_install
+console = Console(log_time=True, log_time_format='%H:%M:%S-%f')
+pretty_install(console=console)
+traceback_install(console=console, extra_lines=1, width=console.width, word_wrap=False, indent_guides=False, suppress=[anyio, starlette, gradio])
already_displayed = {}
@@ -16,8 +24,7 @@ def print_error_explanation(message):
def display(e: Exception, task):
print(f"{task or 'error'}: {type(e).__name__}", file=sys.stderr)
- console = Console()
- console.print_exception(show_locals=False, max_frames=2, extra_lines=1, suppress=[], word_wrap=False, width=min([console.width, 200]))
+ console.print_exception(show_locals=False, max_frames=2, extra_lines=1, suppress=[anyio, starlette, gradio], word_wrap=False, width=min([console.width, 200]))
def display_once(e: Exception, task):
@@ -32,3 +39,7 @@ def run(code, task):
code()
except Exception as e:
display(task, e)
+
+
+def exception():
+ console.print_exception(show_locals=False, max_frames=10, extra_lines=2, suppress=[anyio, starlette, gradio], word_wrap=False, width=min([console.width, 200]))
diff --git a/modules/extensions.py b/modules/extensions.py
index 2ad7f66e2..ea9d8a937 100644
--- a/modules/extensions.py
+++ b/modules/extensions.py
@@ -4,7 +4,7 @@ import sys
import time
import git
-from modules import shared
+from modules import shared, errors
from modules.paths_internal import extensions_dir, extensions_builtin_dir
extensions = []
@@ -44,9 +44,8 @@ class Extension:
try:
if os.path.exists(os.path.join(self.path, ".git")):
repo = git.Repo(self.path)
- except Exception:
- print(f"Error reading github repository info from {self.path}:", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'github info from {self.path}')
if repo is None or repo.bare:
self.remote = None
@@ -101,13 +100,12 @@ def list_extensions():
if not os.path.isdir(extensions_dir):
return
- if shared.opts.disable_all_extensions == "all":
- print("*** \"Disable all extensions\" option was set, will not load any extensions ***")
- elif shared.opts.disable_all_extensions == "extra":
- print("*** \"Disable all extensions\" option was set, will only load built-in extensions ***")
+ if shared.opts.disable_all_extensions == "all" or shared.opts.disable_all_extensions == "extra":
+ shared.log.warning("Option set: Disable all extensions")
extension_paths = []
- for dirname in [extensions_dir, extensions_builtin_dir]:
+ extension_names = []
+ for dirname in [extensions_builtin_dir, extensions_dir]:
if not os.path.isdir(dirname):
return
@@ -115,7 +113,10 @@ def list_extensions():
path = os.path.join(dirname, extension_dirname)
if not os.path.isdir(path):
continue
-
+ if extension_dirname in extension_names:
+ shared.log.info(f'Skipping conflicting extension: {path}')
+ continue
+ extension_names.append(extension_dirname)
extension_paths.append((extension_dirname, path, dirname == extensions_builtin_dir))
for dirname, path, is_builtin in extension_paths:
diff --git a/modules/gfpgan_model.py b/modules/gfpgan_model.py
index 14adfa32f..e68b50dbd 100644
--- a/modules/gfpgan_model.py
+++ b/modules/gfpgan_model.py
@@ -2,7 +2,7 @@ import os
import sys
import modules.face_restoration
-from modules import paths, shared, devices, modelloader
+from modules import paths, shared, devices, modelloader, errors
model_dir = "GFPGAN"
user_path = None
@@ -110,6 +110,5 @@ def setup_model(dirname):
return gfpgan_fix_faces(np_image)
shared.face_restorers.append(FaceRestorerGFPGAN())
- except Exception:
- print("Error setting up GFPGAN:", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.exception(e, 'gfpgan')
diff --git a/modules/hypernetworks/hypernetwork.py b/modules/hypernetworks/hypernetwork.py
index 1ac29c8f1..4aa5ffcdc 100644
--- a/modules/hypernetworks/hypernetwork.py
+++ b/modules/hypernetworks/hypernetwork.py
@@ -11,7 +11,7 @@ import torch
import tqdm
from einops import rearrange, repeat
from ldm.util import default
-from modules import devices, processing, sd_models, shared, sd_samplers, hashes, sd_hijack_checkpoint
+from modules import devices, processing, sd_models, shared, sd_samplers, hashes, sd_hijack_checkpoint, errors
from modules.textual_inversion import textual_inversion, logging
from modules.textual_inversion.learn_schedule import LearnRateScheduler
from torch import einsum
@@ -329,9 +329,8 @@ def load_hypernetwork(name):
try:
hypernetwork.load(path)
- except Exception:
- print(f"Error loading hypernetwork {path}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'hypernetwork load: {path}')
return None
return hypernetwork
@@ -769,8 +768,8 @@ Last saved hypernetwork: {html.escape(last_saved_file)}
Last saved image: {html.escape(last_saved_image)}
"""
- except Exception:
- shared.exception()
+ except Exception as e:
+ errors.display(e, 'hypernetwork train')
finally:
pbar.leave = False
pbar.close()
diff --git a/modules/images.py b/modules/images.py
index 6fab5ba9f..046ae37c2 100644
--- a/modules/images.py
+++ b/modules/images.py
@@ -419,10 +419,9 @@ class FilenameGenerator:
if fun is not None:
try:
replacement = fun(self, *pattern_args)
- except Exception:
+ except Exception as e:
replacement = None
- print(f"Error adding [{pattern}] to filename", file=sys.stderr)
- shared.exception()
+ errors.display(e, 'filename pattern')
if replacement is not None:
res += str(replacement)
@@ -651,9 +650,8 @@ def read_info_from_image(image):
geninfo = f"""{items["Description"]}
Negative prompt: {json_info["uc"]}
Steps: {json_info["steps"]}, Sampler: {sampler}, CFG scale: {json_info["scale"]}, Seed: {json_info["seed"]}, Size: {image.width}x{image.height}, Clip skip: 2, ENSD: 31337"""
- except Exception:
- print("Error parsing NovelAI image generation parameters:", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, 'novelai image parser')
return geninfo, items
diff --git a/modules/interrogate.py b/modules/interrogate.py
index 80b6122f8..66ae32e85 100644
--- a/modules/interrogate.py
+++ b/modules/interrogate.py
@@ -215,9 +215,8 @@ class InterrogateModels:
else:
res += ", " + match
- except Exception:
- print("Error interrogating", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, 'interrogate')
res += ""
self.unload()
diff --git a/modules/localization.py b/modules/localization.py
index 368cecd58..9aed5a971 100644
--- a/modules/localization.py
+++ b/modules/localization.py
@@ -2,6 +2,7 @@ import json
import os
import sys
import modules.shared as shared
+import modules.errors as errors
localizations = {}
@@ -31,8 +32,8 @@ def localization_js(current_localization_name):
try:
with open(fn, "r", encoding="utf8") as file:
data = json.load(file)
- except Exception:
+ except Exception as e:
print(f"Error loading localization from {fn}:", file=sys.stderr)
- shared.exception()
+ errors.display(e, 'localization')
return f"var localization = {json.dumps(data)}\n"
diff --git a/modules/lora b/modules/lora
index 7ad7cac0c..6d5f847ed 160000
--- a/modules/lora
+++ b/modules/lora
@@ -1 +1 @@
-Subproject commit 7ad7cac0c272211abb688168d4c2d4400bef7c51
+Subproject commit 6d5f847edc7eaf858aa6fe060c68875b8da7392a
diff --git a/modules/paths.py b/modules/paths.py
index 0e1e00e72..4a3073295 100644
--- a/modules/paths.py
+++ b/modules/paths.py
@@ -34,10 +34,11 @@ for d, must_exist, what, options in path_dirs:
print(f"Warning: {what} not found at path {must_exist_path}", file=sys.stderr)
else:
d = os.path.abspath(d)
- if "atstart" in options:
- sys.path.insert(0, d)
- else:
- sys.path.append(d)
+ # if "atstart" in options:
+ # sys.path.insert(0, d)
+ # else:
+ # sys.path.append(d)
+ sys.path.append(d)
paths[what] = d
diff --git a/modules/realesrgan_model.py b/modules/realesrgan_model.py
index f919d5d2a..a69f22a74 100644
--- a/modules/realesrgan_model.py
+++ b/modules/realesrgan_model.py
@@ -8,6 +8,7 @@ from basicsr.utils.download_util import load_file_from_url
from modules.upscaler import Upscaler, UpscalerData
from modules.shared import cmd_opts, opts
import modules.shared as shared
+import modules.errors as errors
class UpscalerRealESRGAN(Upscaler):
@@ -26,9 +27,8 @@ class UpscalerRealESRGAN(Upscaler):
if scaler.name in opts.realesrgan_enabled_models:
self.scalers.append(scaler)
- except Exception:
- print("Error importing Real-ESRGAN:", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, 'real-esrgan')
self.enable = False
self.scalers = []
@@ -72,8 +72,7 @@ class UpscalerRealESRGAN(Upscaler):
info.local_data_path = load_file_from_url(url=info.data_path, model_dir=self.model_path, progress=True)
return info
except Exception as e:
- print(f"Error making Real-ESRGAN models list: {e}", file=sys.stderr)
- shared.exception()
+ errors.display(e, 'real-esrgan model list')
return None
def load_models(self, _):
diff --git a/modules/safe.py b/modules/safe.py
index 1e99e9eb9..775f3699d 100644
--- a/modules/safe.py
+++ b/modules/safe.py
@@ -11,7 +11,6 @@ import _codecs
import zipfile
import re
-
# PyTorch 1.13 and later have _TypedStorage renamed to TypedStorage
TypedStorage = torch.storage.TypedStorage if hasattr(torch.storage, 'TypedStorage') else torch.storage._TypedStorage
@@ -127,20 +126,13 @@ def load_with_extra(filename, extra_handler=None, *args, **kwargs):
definitely unsafe.
"""
- from modules import shared
+ from modules import shared, errors
try:
if not shared.cmd_opts.disable_safe_unpickle:
check_pt(filename, extra_handler)
-
- except pickle.UnpicklingError:
- print(f"Error verifying pickled file from {filename}:", file=sys.stderr)
- shared.exception()
- return None
-
- except Exception:
- print(f"Error verifying pickled file from {filename}:", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'verifying pickled file {filename}')
return None
return unsafe_torch_load(filename, *args, **kwargs)
diff --git a/modules/script_callbacks.py b/modules/script_callbacks.py
index 8a96839a4..a339614a8 100644
--- a/modules/script_callbacks.py
+++ b/modules/script_callbacks.py
@@ -2,15 +2,15 @@ import sys
from collections import namedtuple
import inspect
import modules.shared as shared
+import modules.errors as errors
from typing import Optional, Dict, Any
from fastapi import FastAPI
from gradio import Blocks
-def report_exception(c, job):
- print(f"Error executing callback {job} for {c.script}", file=sys.stderr)
- shared.exception()
+def report_exception(e, c, job):
+ errors.display(e, f'executing callback: {c.script} {job}')
class ImageSaveParams:
@@ -105,16 +105,16 @@ def app_started_callback(demo: Optional[Blocks], app: FastAPI):
for c in callback_map['callbacks_app_started']:
try:
c.callback(demo, app)
- except Exception:
- report_exception(c, 'app_started_callback')
+ except Exception as e:
+ report_exception(e, c, 'app_started_callback')
def model_loaded_callback(sd_model):
for c in callback_map['callbacks_model_loaded']:
try:
c.callback(sd_model)
- except Exception:
- report_exception(c, 'model_loaded_callback')
+ except Exception as e:
+ report_exception(e, c, 'model_loaded_callback')
def ui_tabs_callback():
@@ -123,8 +123,8 @@ def ui_tabs_callback():
for c in callback_map['callbacks_ui_tabs']:
try:
res += c.callback() or []
- except Exception:
- report_exception(c, 'ui_tabs_callback')
+ except Exception as e:
+ report_exception(e, c, 'ui_tabs_callback')
return res
@@ -133,96 +133,96 @@ def ui_train_tabs_callback(params: UiTrainTabParams):
for c in callback_map['callbacks_ui_train_tabs']:
try:
c.callback(params)
- except Exception:
- report_exception(c, 'callbacks_ui_train_tabs')
+ except Exception as e:
+ report_exception(e, c, 'callbacks_ui_train_tabs')
def ui_settings_callback():
for c in callback_map['callbacks_ui_settings']:
try:
c.callback()
- except Exception:
- report_exception(c, 'ui_settings_callback')
+ except Exception as e:
+ report_exception(e, c, 'ui_settings_callback')
def before_image_saved_callback(params: ImageSaveParams):
for c in callback_map['callbacks_before_image_saved']:
try:
c.callback(params)
- except Exception:
- report_exception(c, 'before_image_saved_callback')
+ except Exception as e:
+ report_exception(e, c, 'before_image_saved_callback')
def image_saved_callback(params: ImageSaveParams):
for c in callback_map['callbacks_image_saved']:
try:
c.callback(params)
- except Exception:
- report_exception(c, 'image_saved_callback')
+ except Exception as e:
+ report_exception(e, c, 'image_saved_callback')
def cfg_denoiser_callback(params: CFGDenoiserParams):
for c in callback_map['callbacks_cfg_denoiser']:
try:
c.callback(params)
- except Exception:
- report_exception(c, 'cfg_denoiser_callback')
+ except Exception as e:
+ report_exception(e, c, 'cfg_denoiser_callback')
def cfg_denoised_callback(params: CFGDenoisedParams):
for c in callback_map['callbacks_cfg_denoised']:
try:
c.callback(params)
- except Exception:
- report_exception(c, 'cfg_denoised_callback')
+ except Exception as e:
+ report_exception(e, c, 'cfg_denoised_callback')
def before_component_callback(component, **kwargs):
for c in callback_map['callbacks_before_component']:
try:
c.callback(component, **kwargs)
- except Exception:
- report_exception(c, 'before_component_callback')
+ except Exception as e:
+ report_exception(e, c, 'before_component_callback')
def after_component_callback(component, **kwargs):
for c in callback_map['callbacks_after_component']:
try:
c.callback(component, **kwargs)
- except Exception:
- report_exception(c, 'after_component_callback')
+ except Exception as e:
+ report_exception(e, c, 'after_component_callback')
def image_grid_callback(params: ImageGridLoopParams):
for c in callback_map['callbacks_image_grid']:
try:
c.callback(params)
- except Exception:
- report_exception(c, 'image_grid')
+ except Exception as e:
+ report_exception(e, c, 'image_grid')
def infotext_pasted_callback(infotext: str, params: Dict[str, Any]):
for c in callback_map['callbacks_infotext_pasted']:
try:
c.callback(infotext, params)
- except Exception:
- report_exception(c, 'infotext_pasted')
+ except Exception as e:
+ report_exception(e, c, 'infotext_pasted')
def script_unloaded_callback():
for c in reversed(callback_map['callbacks_script_unloaded']):
try:
c.callback()
- except Exception:
- report_exception(c, 'script_unloaded')
+ except Exception as e:
+ report_exception(e, c, 'script_unloaded')
def before_ui_callback():
for c in reversed(callback_map['callbacks_before_ui']):
try:
c.callback()
- except Exception:
- report_exception(c, 'before_ui')
+ except Exception as e:
+ report_exception(e, c, 'before_ui')
def add_callback(callbacks, fun):
diff --git a/modules/script_loading.py b/modules/script_loading.py
index e919d8c58..cbfb214c2 100644
--- a/modules/script_loading.py
+++ b/modules/script_loading.py
@@ -1,6 +1,7 @@
import os
import sys
import modules.shared as shared
+import modules.errors as errors
import importlib.util
from types import ModuleType
@@ -27,6 +28,5 @@ def preload_extensions(extensions_dir, parser):
if hasattr(module, 'preload'):
module.preload(parser)
- except Exception:
- print(f"Error running preload() for {preload_script}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'extension preload: {preload_script}')
diff --git a/modules/scripts.py b/modules/scripts.py
index 233fa83df..06235344b 100644
--- a/modules/scripts.py
+++ b/modules/scripts.py
@@ -5,7 +5,7 @@ from collections import namedtuple
import gradio as gr
-from modules import shared, paths, script_callbacks, extensions, script_loading, scripts_postprocessing
+from modules import shared, paths, script_callbacks, extensions, script_loading, scripts_postprocessing, errors
AlwaysVisible = object()
@@ -255,9 +255,8 @@ def load_scripts():
script_module = script_loading.load_module(scriptfile.path)
register_scripts_from_module(script_module)
- except Exception:
- print(f"Error loading script: {scriptfile.filename}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'loading script: {scriptfile.filename}')
finally:
@@ -269,9 +268,8 @@ def wrap_call(func, filename, funcname, *args, default=None, **kwargs):
try:
res = func(*args, **kwargs)
return res
- except Exception:
- print(f"Error calling: {filename}/{funcname}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'calling script: {filename}/{funcname}')
return default
@@ -415,70 +413,62 @@ class ScriptRunner:
try:
script_args = p.script_args[script.args_from:script.args_to]
script.process(p, *script_args)
- except Exception:
- print(f"Error running process: {script.filename}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'running script process: {script.filename}')
def before_process_batch(self, p, **kwargs):
for script in self.alwayson_scripts:
try:
script_args = p.script_args[script.args_from:script.args_to]
script.before_process_batch(p, *script_args, **kwargs)
- except Exception:
- print(f"Error running before_process_batch: {script.filename}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'running script before process batch: {script.filename}')
def process_batch(self, p, **kwargs):
for script in self.alwayson_scripts:
try:
script_args = p.script_args[script.args_from:script.args_to]
script.process_batch(p, *script_args, **kwargs)
- except Exception:
- print(f"Error running process_batch: {script.filename}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'running script process batch: {script.filename}')
def postprocess(self, p, processed):
for script in self.alwayson_scripts:
try:
script_args = p.script_args[script.args_from:script.args_to]
script.postprocess(p, processed, *script_args)
- except Exception:
- print(f"Error running postprocess: {script.filename}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'running script postprocess: {script.filename}')
def postprocess_batch(self, p, images, **kwargs):
for script in self.alwayson_scripts:
try:
script_args = p.script_args[script.args_from:script.args_to]
script.postprocess_batch(p, *script_args, images=images, **kwargs)
- except Exception:
- print(f"Error running postprocess_batch: {script.filename}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'running script before postprocess batch: {script.filename}')
def postprocess_image(self, p, pp: PostprocessImageArgs):
for script in self.alwayson_scripts:
try:
script_args = p.script_args[script.args_from:script.args_to]
script.postprocess_image(p, pp, *script_args)
- except Exception:
- print(f"Error running postprocess_batch: {script.filename}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'running script postprocess image: {script.filename}')
def before_component(self, component, **kwargs):
for script in self.scripts:
try:
script.before_component(component, **kwargs)
- except Exception:
- print(f"Error running before_component: {script.filename}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'running script before component: {script.filename}')
def after_component(self, component, **kwargs):
for script in self.scripts:
try:
script.after_component(component, **kwargs)
- except Exception:
- print(f"Error running after_component: {script.filename}", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'running script after component: {script.filename}')
def reload_sources(self, cache):
for si, script in list(enumerate(self.scripts)):
diff --git a/modules/sd_models.py b/modules/sd_models.py
index 8ce39868f..97202c8f5 100644
--- a/modules/sd_models.py
+++ b/modules/sd_models.py
@@ -120,7 +120,6 @@ def list_models():
if os.path.exists(cmd_ckpt):
checkpoint_info = CheckpointInfo(cmd_ckpt)
checkpoint_info.register()
-
shared.opts.data['sd_model_checkpoint'] = checkpoint_info.title
elif cmd_ckpt is not None and cmd_ckpt != shared.default_sd_model_file:
print("Checkpoint in --ckpt argument not found", file=sys.stderr)
@@ -129,7 +128,7 @@ def list_models():
checkpoint_info = CheckpointInfo(filename)
checkpoint_info.register()
- print('Available models:', len(checkpoints_list))
+ shared.log.info(f'Available models: {shared.opts.ckpt_dir} {len(checkpoints_list)}')
def get_closet_checkpoint_match(search_string):
@@ -257,9 +256,7 @@ def read_state_dict(checkpoint_file):
pl_sd = torch.load(buffer, map_location='cpu')
sd = get_state_dict_from_checkpoint(pl_sd)
except Exception as e:
- from rich.console import Console
- console = Console()
- console.print_exception(show_locals=False, max_frames=2, extra_lines=1, suppress=[], word_wrap=False, width=min([console.width, 200]))
+ errors.display(e, f'loading model: {checkpoint_file}')
sd = None
return sd
diff --git a/modules/shared.py b/modules/shared.py
index 35e7d1427..d241e31f1 100644
--- a/modules/shared.py
+++ b/modules/shared.py
@@ -5,31 +5,23 @@ import os
import sys
import time
+from setup import log as setup_log
+
import gradio as gr
import tqdm
-from rich import print
import modules.interrogate
import modules.memmon
import modules.styles
import modules.devices as devices
-from modules import script_loading, errors, ui_components, shared_items, cmd_args
+from modules import script_loading, errors, ui_components, shared_items, cmd_args, errors
from modules.paths_internal import models_path, script_path, data_path, sd_configs_path, sd_default_config, sd_model_file, default_sd_model_file, extensions_dir, extensions_builtin_dir
demo = None
+log = setup_log
parser = cmd_args.parser
-try:
- from rich.pretty import install as pretty_install
- from rich.traceback import install as traceback_install
- from rich.console import Console
- console = Console(log_time=True, log_time_format='%H:%M:%S-%f')
- pretty_install(console=console)
- traceback_install(console=console, extra_lines=1, width=console.width, word_wrap=False, indent_guides=False, show_locals=False, max_frames=2)
-except:
- console = None
-
script_loading.preload_extensions(extensions_dir, parser)
script_loading.preload_extensions(extensions_builtin_dir, parser)
@@ -522,11 +514,11 @@ class Options:
for k, v in self.data.items():
info = self.data_labels.get(k, None)
if info is not None and not self.same_type(info.default, v):
- print(f"Warning: bad setting value: {k}: {v} ({type(v).__name__}; expected {type(info.default).__name__})", file=sys.stderr)
+ log.error(f"Warning: bad setting value: {k}: {v} ({type(v).__name__}; expected {type(info.default).__name__})", file=sys.stderr)
bad_settings += 1
if bad_settings > 0:
- print(f"The program is likely to not work with bad settings.\nSettings file: {filename}\nEither fix the file, or delete it and restart.", file=sys.stderr)
+ log.error(f"The program is likely to not work with bad settings.\nSettings file: {filename}\nEither fix the file, or delete it and restart.", file=sys.stderr)
def onchange(self, key, func, call=True):
item = self.data_labels.get(key)
@@ -663,10 +655,3 @@ def html(filename):
return file.read()
return ""
-
-def exception():
- if console is not None:
- console.print_exception(show_locals=False, max_frames=10, extra_lines=2, suppress=[gr], word_wrap=False, width=min([console.width, 200]))
- else:
- import traceback
- print(traceback.format_exc(), file=sys.stderr)
diff --git a/modules/textual_inversion/textual_inversion.py b/modules/textual_inversion/textual_inversion.py
index 685f33f8d..dd3a4fc08 100644
--- a/modules/textual_inversion/textual_inversion.py
+++ b/modules/textual_inversion/textual_inversion.py
@@ -14,7 +14,7 @@ import numpy as np
from PIL import Image, PngImagePlugin
from torch.utils.tensorboard import SummaryWriter
-from modules import shared, devices, sd_hijack, processing, sd_models, images, sd_samplers, sd_hijack_checkpoint
+from modules import shared, devices, sd_hijack, processing, sd_models, images, sd_samplers, sd_hijack_checkpoint, errors
import modules.textual_inversion.dataset
from modules.textual_inversion.learn_schedule import LearnRateScheduler
@@ -207,9 +207,8 @@ class EmbeddingDatabase:
continue
self.load_from_file(fullfn, fn)
- except Exception:
- print(f"Error loading embedding {fn}:", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'embedding load {fn}')
continue
def load_textual_inversion_embeddings(self, force_reload=False):
@@ -625,8 +624,8 @@ Last saved image: {html.escape(last_saved_image)}
"""
filename = os.path.join(shared.opts.embeddings_dir, f'{embedding_name}.pt')
save_embedding(embedding, optimizer, checkpoint, embedding_name, filename, remove_cached_checksum=True)
- except Exception:
- shared.exception()
+ except Exception as e:
+ errors.display(e, 'embedding train')
pass
finally:
pbar.leave = False
diff --git a/modules/ui.py b/modules/ui.py
index db3c36515..f8a8adfe9 100644
--- a/modules/ui.py
+++ b/modules/ui.py
@@ -8,7 +8,6 @@ import random
import sys
import tempfile
import time
-import traceback
from functools import partial, reduce
import warnings
@@ -31,6 +30,7 @@ import modules.gfpgan_model
import modules.hypernetworks.ui
import modules.scripts
import modules.shared as shared
+import modules.errors as errors
import modules.styles
import modules.textual_inversion.ui
from modules import prompt_parser
@@ -1581,8 +1581,7 @@ def create_ui():
try:
results = modules.extras.run_modelmerger(*args)
except Exception as e:
- print("Error loading/saving model file:", file=sys.stderr)
- print(traceback.format_exc(), file=sys.stderr)
+ errors.display(e, 'model merge')
modules.sd_models.list_models() # to remove the potentially missing models from the list
return [*[gr.Dropdown.update(choices=modules.sd_models.checkpoint_tiles()) for _ in range(4)], f"Error merging checkpoints: {e}"]
return results
@@ -1623,10 +1622,9 @@ def create_ui():
if os.path.exists(ui_config_file):
with open(ui_config_file, "r", encoding="utf8") as file:
ui_settings = json.load(file)
- except Exception:
+ except Exception as e:
error_loading = True
- print("Error loading settings:", file=sys.stderr)
- print(traceback.format_exc(), file=sys.stderr)
+ errors.display(e, 'loading ui settings')
def loadsave(path, x):
def apply_field(obj, field, condition=None, init_field=None):
diff --git a/modules/ui_extensions.py b/modules/ui_extensions.py
index ca92ccee0..74770bc97 100644
--- a/modules/ui_extensions.py
+++ b/modules/ui_extensions.py
@@ -10,7 +10,7 @@ import html
import shutil
import errno
-from modules import extensions, shared, paths
+from modules import extensions, shared, paths, errors
from modules.call_queue import wrap_gradio_gpu_call
available_extensions = {"extensions": []}
@@ -37,9 +37,8 @@ def apply_and_restart(disable_list, update_list, disable_all):
try:
ext.fetch_and_reset_hard()
- except Exception:
- print(f"Error getting updates for {ext.name}:", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'extensions apply update: {ext.name}')
shared.opts.disabled_extensions = disabled
shared.opts.disable_all_extensions = disable_all
@@ -67,8 +66,7 @@ def check_updates(id_task, disable_list):
if 'FETCH_HEAD' not in str(e):
raise
except Exception:
- print(f"Error checking updates for {ext.name}:", file=sys.stderr)
- shared.exception()
+ errors.display(e, f'extensions check update: {ext.name}')
shared.state.nextjob()
diff --git a/scripts/prompts_from_file.py b/scripts/prompts_from_file.py
index d5f029362..e6d5c5a39 100644
--- a/scripts/prompts_from_file.py
+++ b/scripts/prompts_from_file.py
@@ -9,7 +9,7 @@ import shlex
import modules.scripts as scripts
import gradio as gr
-from modules import sd_samplers
+from modules import sd_samplers, errors
from modules.processing import Processed, process_images
from PIL import Image
from modules.shared import opts, cmd_opts, state
@@ -139,9 +139,8 @@ class Script(scripts.Script):
if "--" in line:
try:
args = cmdargs(line)
- except Exception:
- print(f"Error parsing line {line} as commandline:", file=sys.stderr)
- shared.exception()
+ except Exception as e:
+ errors.display(e, f'parsing prompts: {line}')
args = {"prompt": line}
else:
args = {"prompt": line}
diff --git a/setup.py b/setup.py
index cc478ccd8..9a125a7c3 100644
--- a/setup.py
+++ b/setup.py
@@ -231,11 +231,12 @@ def run_extension_installer(extension_dir):
# run installer for each installed and enabled extension and optionally update them
def install_extensions():
+ settings = {}
+ if os.path.isfile('config.json'):
+ with open('config.json', "r", encoding="utf8") as file:
+ settings = json.load(file)
+
def list_extensions(dir):
- settings = {}
- if os.path.isfile('config.json'):
- with open('config.json', "r", encoding="utf8") as file:
- settings = json.load(file)
if settings.get('disable_all_extensions', 'none') != 'none':
log.debug(f'Disabled extensions: all')
return []
@@ -247,7 +248,8 @@ def install_extensions():
extensions_builtin_dir = os.path.join(os.path.dirname(__file__), 'extensions-builtin')
extensions = list_extensions(extensions_builtin_dir)
- log.info(f'Built-in extensions: {extensions}')
+ log.info(f'Extensions disabled: {settings.get("disabled_extensions", [])}')
+ log.info(f'Extensions built-in: {extensions}')
for ext in extensions:
if not args.noupdate:
update(os.path.join(extensions_builtin_dir, ext))
@@ -256,7 +258,7 @@ def install_extensions():
extensions_dir = os.path.join(os.path.dirname(__file__), 'extensions')
extensions = list_extensions(extensions_dir)
- log.info(f'Enabled extensions: {extensions}')
+ log.info(f'Extensions enabled: {extensions}')
for ext in extensions:
if not args.noupdate:
update(os.path.join(extensions_dir, ext))