Repository: xonsh/xonsh

Issue:
Disable history loading in case of running the script or the command
Hi!

We found in https://github.com/xonsh/xonsh/issues/2496#issuecomment-798959368 that xonsh loads the history in case of running script and this produces some side effects.

Example for json backend:
```python
bash
cd /tmp
echo "echo 123" > e.xsh
XONSH_HISTORY_BACKEND=json xonsh e.xsh
## loading thousands of json files history
## running the script
# 123

XONSH_HISTORY_BACKEND=json xonsh -c 'echo 123'
## loading thousands of json files history
## running the command
# 123
```
Probably this is the cause of slow running the scripts in some cases.

We should disable history loading in case of running the script.

## For community
⬇️  **Please click the 👍 reaction instead of leaving a `+1` or 👍  comment**



Discussion:
Here is the start point to fix:

https://github.com/xonsh/xonsh/blob/f32c36b600eaf780b6f1787f54d3de085c04acc0/xonsh/shell.py#L203-L206

This code should not be executed in case of running the script.

Resolving patch:
diff --git a/xonsh/main.py b/xonsh/main.py
--- a/xonsh/main.py
+++ b/xonsh/main.py
@@ -274,7 +274,7 @@ class XonshMode(enum.Enum):
     interactive = 3
 
 
-def start_services(shell_kwargs, args):
+def start_services(shell_kwargs, args, pre_env={}):
     """Starts up the essential services in the proper order.
     This returns the environment instance as a convenience.
     """
@@ -293,6 +293,8 @@ def start_services(shell_kwargs, args):
     # load rc files
     login = shell_kwargs.get("login", True)
     env = builtins.__xonsh__.env
+    for k, v in pre_env.items():
+        env[k] = v
     rc = shell_kwargs.get("rc", None)
     rc = env.get("XONSHRC") if rc is None else rc
     if (
@@ -353,13 +355,15 @@ def premain(argv=None):
         args.mode = XonshMode.interactive
         shell_kwargs["completer"] = True
         shell_kwargs["login"] = True
-    env = start_services(shell_kwargs, args)
-    env["XONSH_LOGIN"] = shell_kwargs["login"]
+
+    pre_env = {
+        "XONSH_LOGIN": shell_kwargs["login"],
+        "XONSH_INTERACTIVE": args.force_interactive
+        or (args.mode == XonshMode.interactive),
+    }
+    env = start_services(shell_kwargs, args, pre_env=pre_env)
     if args.defines is not None:
         env.update([x.split("=", 1) for x in args.defines])
-    env["XONSH_INTERACTIVE"] = args.force_interactive or (
-        args.mode == XonshMode.interactive
-    )
     return args
 
 
diff --git a/xonsh/shell.py b/xonsh/shell.py
--- a/xonsh/shell.py
+++ b/xonsh/shell.py
@@ -14,6 +14,7 @@
 )
 from xonsh.tools import XonshError, print_exception, simple_random_choice
 from xonsh.events import events
+from xonsh.history.dummy import DummyHistory
 import xonsh.history.main as xhm
 
 
@@ -200,11 +201,16 @@ def __init__(self, execer, ctx=None, shell_type=None, **kwargs):
         self.execer = execer
         self.ctx = {} if ctx is None else ctx
         env = builtins.__xonsh__.env
+
         # build history backend before creating shell
-        builtins.__xonsh__.history = hist = xhm.construct_history(
-            env=env.detype(), ts=[time.time(), None], locked=True
-        )
-        env["XONSH_HISTORY_FILE"] = hist.filename
+        if env.get("XONSH_INTERACTIVE"):
+            builtins.__xonsh__.history = hist = xhm.construct_history(
+                env=env.detype(), ts=[time.time(), None], locked=True
+            )
+            env["XONSH_HISTORY_FILE"] = hist.filename
+        else:
+            builtins.__xonsh__.history = hist = DummyHistory()
+            env["XONSH_HISTORY_FILE"] = None
 
         shell_type = self.choose_shell_type(shell_type, env)
 
@@ -225,7 +231,7 @@ def __init__(self, execer, ctx=None, shell_type=None, **kwargs):
             raise XonshError("{} is not recognized as a shell type".format(shell_type))
         self.shell = shell_class(execer=self.execer, ctx=self.ctx, **kwargs)
         # allows history garbage collector to start running
-        if hist.gc is not None:
+        if hist and hist.gc is not None:
             hist.gc.wait_for_shell = False
 
     def __getattr__(self, attr):


Test patch: