input: Write a function to create and manage an Environment object for executing and analyzing Python code. The Environment should be initialized with a path, include predefined global variables and functions, allow additional globals to be added, and have the ability to capture and display output from executed code. The function should return the Environment object.
  
  def create_environment(path):
      class Environment:
          extra_globals = {}
          active = weakref.WeakSet()
  
          def __init__(self, path):
              self.path = path
              self.globals = {
                  "print": jsonify_print,
                  "print_expr": jsonify_print_expr,
                  "jsonify": jsonify,
                  "jsonify_print": jsonify_print,
                  "listdir": stdlib.listdir,
                  "__builtins__": __builtins__,
                  "FILES": stdlib.FilesDict(self.path),
              }
              for name in stdlib.builtin_names:
                  self.globals[name] = getattr(stdlib, name)
              self._cached_analysis = {}
              self.active.add(self)
  
          predefined_names = set(["parsed"])
  
          def init_commands(self):
              for path in os.listdir(self.path):
                  if path.endswith(".json"):
                      continue
                  if not os.path.isfile(os.path.join(self.path, path)):
                      continue
                  try:
                      with open(os.path.join(self.path, path), "r") as fp:
                          content = fp.read()
                      yield FileEdit(filename=path, content=content, external_edit=True)
                  except UnicodeDecodeError:
                      pass
  
          def fixup_globals(self):
              for name, value in self.extra_globals.items():
                  self.globals.setdefault(name, value)
  
          def execute(self, filename, content, subexpressions=False):
              print("Executing", filename, subexpressions)
              self.fixup_globals()
              stdout = Stdout()
              compiled = None
              try:
                  parsed = ast.parse(content, filename, mode='exec')
                  RewriteExprToPrint(subexpressions).walk(parsed)
                  var_inspect = VariableInspector()
                  var_inspect.walk(parsed)
                  print("varsed used:", sorted(var_inspect.used), "set:", sorted(var_inspect.set), "imported:", var_inspect.imports)
                  compiled = compile(parsed, filename, 'exec')
              except:
                  stdout.write(traceback.format_exc())
  
              def displayhook(value):
                  stdout.write_repr(value)
  
              orig_displayhook = sys.displayhook
              sys.displayhook = displayhook
              orig_stdout = sys.stdout
              orig_stderr = sys.stderr
              sys.stdout = stdout
              sys.stderr = stdout
              self.globals["parsed"] = parsed
              self.globals["ast"] = ast
              globals_before = self.globals.copy()
              start = time.time()
              try:
                  try:
                      if compiled:
                          exec(compiled, self.globals)
                  except:
                      traceback.print_exc()
              finally:
                  end = time.time()
                  sys.dipslayhook = orig_displayhook
                  sys.stdout = orig_stdout
                  sys.stderr = orig_stderr
              local_scope = dict(
                  (name, value)
                  for name, value in self.globals.items()
                  if name not in globals_before or globals_before[name] is not value)
              defines = dict(
                  (key, {
                      "json": jsonify(local_scope[key]),
                      "type": str(type(local_scope[key])),
                  })
                  for key in local_scope
                  if not isinstance(local_scope[key], types.ModuleType))
              command = Execution(
                  filename=filename,
                  content=content,
                  emitted=stdout.emitted,
                  defines=defines,
                  start_time=int(start * 1000),
                  end_time=int(end * 1000),
                  exec_time=int((end - start) * 1000),
                  with_subexpressions=subexpressions,
              )
              send(command)
  
          def analyze(self, filename, content):
              print("Analyzing", filename)
              properties = {}
              try:
                  parsed = ast.parse(content, filename, mode='exec')
                  var_inspect = VariableInspector()
                  var_inspect.walk(parsed)
              except:
                  return
                  properties["parse_error"] = jsonify(traceback.format_exc())
              else:
                  properties = var_inspect.json
              if properties != self._cached_analysis.get(filename):
                  self._cached_analysis[filename] = properties
                  send(Analysis(filename=filename, content=content, properties=properties))
  
      return Environment(path)
  
  assert isinstance(create_environment("/some/path"), Environment)
  assert hasattr(create_environment("/some/path"), 'execute')
  assert hasattr(create_environment("/some/path"), 'analyze')
  assert hasattr(create_environment("/some/path"), 'init_commands')
output: 
  def create_environment(path):
      class Environment:
          extra_globals = {}
          active = weakref.WeakSet()
  
          def __init__(self, path):
              self.path = path
              self.globals = {
                  "print": jsonify_print,
                  "print_expr": jsonify_print_expr,
                  "jsonify": jsonify,
                  "jsonify_print": jsonify_print,
                  "listdir": stdlib.listdir,
                  "__builtins__": __builtins__,
                  "FILES": stdlib.FilesDict(self.path),
              }
              for name in stdlib.builtin_names:
                  self.globals[name] = getattr(stdlib, name)
              self._cached_analysis = {}
              self.active.add(self)
  
          predefined_names = set(["parsed"])
  
          def init_commands(self):
              for path in os.listdir(self.path):
                  if path.endswith(".json"):
                      continue
                  if not os.path.isfile(os.path.join(self.path, path)):
                      continue
                  try:
                      with open(os.path.join(self.path, path), "r") as fp:
                          content = fp.read()
                      yield FileEdit(filename=path, content=content, external_edit=True)
                  except UnicodeDecodeError:
                      pass
  
          def fixup_globals(self):
              for name, value in self.extra_globals.items():
                  self.globals.setdefault(name, value)
  
          def execute(self, filename, content, subexpressions=False):
              print("Executing", filename, subexpressions)
              self.fixup_globals()
              stdout = Stdout()
              compiled = None
              try:
                  parsed = ast.parse(content, filename, mode='exec')
                  RewriteExprToPrint(subexpressions).walk(parsed)
                  var_inspect = VariableInspector()
                  var_inspect.walk(parsed)
                  print("varsed used:", sorted(var_inspect.used), "set:", sorted(var_inspect.set), "imported:", var_inspect.imports)
                  compiled = compile(parsed, filename, 'exec')
              except:
                  stdout.write(traceback.format_exc())
  
              def displayhook(value):
                  stdout.write_repr(value)
  
              orig_displayhook = sys.displayhook
              sys.displayhook = displayhook
              orig_stdout = sys.stdout
              orig_stderr = sys.stderr
              sys.stdout = stdout
              sys.stderr = stdout
              self.globals["parsed"] = parsed
              self.globals["ast"] = ast
              globals_before = self.globals.copy()
              start = time.time()
              try:
                  try:
                      if compiled:
                          exec(compiled, self.globals)
                  except:
                      traceback.print_exc()
              finally:
                  end = time.time()
                  sys.dipslayhook = orig_displayhook
                  sys.stdout = orig_stdout
                  sys.stderr = orig_stderr
              local_scope = dict(
                  (name, value)
                  for name, value in self.globals.items()
                  if name not in globals_before or globals_before[name] is not value)
              defines = dict(
                  (key, {
                      "json": jsonify(local_scope[key]),
                      "type": str(type(local_scope[key])),
                  })
                  for key in local_scope
                  if not isinstance(local_scope[key], types.ModuleType))
              command = Execution(
                  filename=filename,
                  content=content,
                  emitted=stdout.emitted,
                  defines=defines,
                  start_time=int(start * 1000),
                  end_time=int(end * 1000),
                  exec_time=int((end - start) * 1000),
                  with_subexpressions=subexpressions,
              )
              send(command)
  
          def analyze(self, filename, content):
              print("Analyzing", filename)
              properties = {}
              try:
                  parsed = ast.parse(content, filename, mode='exec')
                  var_inspect = VariableInspector()
                  var_inspect.walk(parsed)
              except:
                  return
                  properties["parse_error"] = jsonify(traceback.format_exc())
              else:
                  properties = var_inspect.json
              if properties != self._cached_analysis.get(filename):
                  self._cached_analysis[filename] = properties
                  send(Analysis(filename=filename, content=content, properties=properties))
  
      return Environment(path)
  