input: Write a function to implement an `Environment` object capable of executing and analyzing Python code. The function should create an environment that includes predefined global variables and functions, and can add additional global variables. It should execute Python code and analyze it for variable usage and imports. The environment also includes a `stdout` object to capture and display output from executed code.
  assert Environment('example_path').execute('example.py', 'print("Hello, World!")') == True
  assert Environment('example_path').analyze('example.py', 'import os\nx = 10\nprint(x)') == {'variables_used': ['x'], 'variables_set': ['x'], 'imports': ['os']}
  assert Environment('example_path').fixup_globals() == None
  assert Environment('example_path').globals['print'] == jsonify_print
  assert Environment('example_path').globals['listdir'] == stdlib.listdir
output: def __init__(self, path):
      self.path = path
      self.globals = {'print': jsonify_print, 'listdir': stdlib.listdir}
      self.stdout = []
  
  def execute(self, filename, code):
      try:
          exec(code, self.globals)
          return True
      except Exception as e:
          return False
  
  def analyze(self, filename, code):
      variables_used = []
      variables_set = []
      imports = []
      
      tree = ast.parse(code)
      
      for node in ast.walk(tree):
          if isinstance(node, ast.Name) and isinstance(node.ctx, ast.Load):
              variables_used.append(node.id)
          elif isinstance(node, ast.Name) and isinstance(node.ctx, ast.Store):
              variables_set.append(node.id)
          elif isinstance(node, ast.Import):
              for n in node.names:
                  imports.append(n.name)
          elif isinstance(node, ast.ImportFrom):
              imports.append(node.module)
      
      return {'variables_used': variables_used, 'variables_set': variables_set, 'imports': imports}
  
  def fixup_globals(self):
      pass