input: Create a class `Environment` that can execute and analyze Python code. The environment includes a set of predefined global variables and functions, as well as the ability to add additional global variables. The environment can execute Python code and analyze it for variable usage and imports. The environment also includes a `stdout` object that can be used to capture and display output from executed code.
  
  Write a function to initialize the `Environment` class and execute and analyze Python code. The function should take the path to a directory containing Python files as input. Additionally, it should be able to handle the execution of Python code with subexpressions and analyze the code for variable usage and imports. The function should return the analysis results and captured output from the executed code.
  
  
  class Environment:
      # Class implementation here
      
  def analyze_and_execute_code(path: str, filename: str, content: str, subexpressions: bool = False) -> dict:
      env = Environment(path)
      env.execute(filename, content, subexpressions=subexpressions)
      env.analyze(filename, content)
      return {"analysis": env._cached_analysis, "output": env.stdout.emitted}
  
  
  assert analyze_and_execute_code("example/path", "example.py", "print(1 + 2)", subexpressions=True) == {"analysis": {"variables_used": ["print"], "variables_set": [], "imports": []}, "output": [{'type': 'print', 'time': 1639000000000, 'parts': [{'type': 'str', 'str': '3'}]}]}
  assert analyze_and_execute_code("example/path", "example.py", "a = 5\nprint(a + 2)", subexpressions=False) == {"analysis": {"variables_used": ["a", "print"], "variables_set": ["a"], "imports": []}, "output": [{'type': 'print', 'time': 1639000000000, 'parts': [{'type': 'str', 'str': '7'}]}]}
  assert analyze_and_execute_code("example/path", "example.py", "import math\nprint(math.pi)", subexpressions=False) == {"analysis": {"variables_used": ["math", "print"], "variables_set": [], "imports": ["math"]}, "output": [{'type': 'print', 'time': 1639000000000, 'parts': [{'type': 'str', 'str': '3.141592653589793'}]}]}
  
output:     
  class Environment:
      def __init__(self, path: str):
          self.path = path
          self._cached_analysis = {}
          self.stdout = StdoutCapture()
          self.globals = {"__builtins__": __builtins__}
  
      def execute(self, filename: str, content: str, subexpressions: bool = False):
          if subexpressions:
              self._execute_subexpressions(content)
          else:
              exec(content, self.globals)
  
      def _execute_subexpressions(self, content: str):
          tree = ast.parse(content)
          for node in ast.walk(tree):
              if isinstance(node, ast.Expr):
                  try:
                      result = eval(compile(ast.Expression(node.value), "<string>", "eval"), self.globals)
                      print(result)
                  except Exception as e:
                      pass
  
      def analyze(self, filename: str, content: str):
          tree = ast.parse(content)
          variables_used = set()
          variables_set = set()
          imports = set()
  
          for node in ast.walk(tree):
              if isinstance(node, ast.Name) and isinstance(node.ctx, ast.Load):
                  variables_used.add(node.id)
              elif isinstance(node, ast.Name) and isinstance(node.ctx, ast.Store):
                  variables_set.add(node.id)
              elif isinstance(node, ast.Import):
                  for n in node.names:
                      imports.add(n.name)
              elif isinstance(node, ast.ImportFrom):
                  imports.add(node.module)
  
          self._cached_analysis = {
              "variables_used": list(variables_used),
              "variables_set": list(variables_set),
              "imports": list(imports)
          }
  
  class StdoutCapture:
      def __init__(self):
          self.emitted = []
  
      def write(self, text):
          self.emitted.append({
              'type': 'print',
              'time': int(time.time() * 1000),
              'parts': [{'type': 'str', 'str': text.strip()}]
          })
  
      def flush(self):
          pass
  
  import ast
  import time
  import sys
  sys.stdout = StdoutCapture()
  