[Telemetry] Update Python code to use print function

Updated Python code inside Telemetry to use print function instead of
print statement. The changes were first generated by modernize module
and then manually reviewed and edited.

Bug: chromium:1198408
Change-Id: Ib1d9676be9da255bdb7efbda764a6cb8b4e714cc
Reviewed-on: https://chromium-review.googlesource.com/c/catapult/+/2823057
Reviewed-by: Wenbin Zhang <wenbinzhang@google.com>
Commit-Queue: John Chen <johnchen@chromium.org>
diff --git a/telemetry/build/linux_setup_msr.py b/telemetry/build/linux_setup_msr.py
index 84faca9..a4a4e20 100755
--- a/telemetry/build/linux_setup_msr.py
+++ b/telemetry/build/linux_setup_msr.py
@@ -12,6 +12,7 @@
 #
 # This script is currently Debian/Ubuntu specific.
 
+from __future__ import print_function
 import os
 import subprocess
 import sys
@@ -21,10 +22,10 @@
 
 def _Usage(prog_name):
   """Print a help message."""
-  print 'Run "%s" as a regular user to check if reading from the MSR ' \
-      'is possible.' % prog_name
-  print 'Run "%s enable" as root to automatically set up reading from ' \
-      'the MSR.' % prog_name
+  print('Run "%s" as a regular user to check if reading from the MSR ' \
+      'is possible.' % prog_name)
+  print('Run "%s enable" as root to automatically set up reading from ' \
+      'the MSR.' % prog_name)
 
 
 def _CheckMsrKernelModule():
@@ -36,7 +37,7 @@
     raise OSError('lsmod failed')
 
   if not any([line.startswith('msr ') for line in stdout.splitlines()]):
-    print 'Error: MSR module not loaded.'
+    print('Error: MSR module not loaded.')
     return False
 
   return True
@@ -45,11 +46,11 @@
 def _CheckMsrDevNodes():
   """Check whether the MSR /dev files have the right permissions."""
   if not os.path.exists(MSR_DEV_FILE_PATH):
-    print 'Error: %s does not exist.' % MSR_DEV_FILE_PATH
+    print('Error: %s does not exist.' % MSR_DEV_FILE_PATH)
     return False
 
   if not os.access(MSR_DEV_FILE_PATH, os.R_OK):
-    print 'Error: Cannot read from %s' % MSR_DEV_FILE_PATH
+    print('Error: Cannot read from %s' % MSR_DEV_FILE_PATH)
     return False
 
   return True
@@ -58,7 +59,7 @@
 def _CheckRdmsr():
   """Check and make sure /usr/sbin/rdmsr is set up correctly."""
   if not os.access(RDMSR_PATH, os.X_OK):
-    print 'Error: %s missing or not executable.' % RDMSR_PATH
+    print('Error: %s missing or not executable.' % RDMSR_PATH)
     return False
 
   proc = subprocess.Popen(['/sbin/getcap', RDMSR_PATH], stdout=subprocess.PIPE)
@@ -68,7 +69,7 @@
     raise OSError('getcap failed')
 
   if 'cap_sys_rawio+ep' not in stdout:
-    print 'Error: /usr/sbin/rdmsr needs RAWIO capability.'
+    print('Error: /usr/sbin/rdmsr needs RAWIO capability.')
     return False
 
   return True
@@ -77,7 +78,7 @@
 def _RunAllChecks():
   """Check to make sure it is possible to read from the MSRs."""
   if os.geteuid() == 0:
-    print 'WARNING: Running as root, msr permission check likely inaccurate.'
+    print('WARNING: Running as root, msr permission check likely inaccurate.')
 
   has_dev_node = _CheckMsrDevNodes() if _CheckMsrKernelModule() else False
   has_rdmsr = _CheckRdmsr()
@@ -89,32 +90,32 @@
 
   Needs to run as root."""
   if os.geteuid() != 0:
-    print 'Error: Must run "%s enable" as root.' % prog_name
+    print('Error: Must run "%s enable" as root.' % prog_name)
     return False
 
-  print 'Loading msr kernel module.'
+  print('Loading msr kernel module.')
   ret = subprocess.call(['/sbin/modprobe', 'msr'])
   if ret != 0:
-    print 'Error: Cannot load msr module.'
+    print('Error: Cannot load msr module.')
     return False
 
-  print 'Running chmod on %s.' % MSR_DEV_FILE_PATH
+  print('Running chmod on %s.' % MSR_DEV_FILE_PATH)
   ret = subprocess.call(['/bin/chmod', 'a+r', MSR_DEV_FILE_PATH])
   if ret != 0:
-    print 'Error: Cannot chmod %s.' % MSR_DEV_FILE_PATH
+    print('Error: Cannot chmod %s.' % MSR_DEV_FILE_PATH)
     return False
 
   if not os.access(RDMSR_PATH, os.F_OK):
-    print 'Need to install the msr-tools package.'
+    print('Need to install the msr-tools package.')
     ret = subprocess.call(['/usr/bin/apt-get', 'install', '-y', 'msr-tools'])
     if ret != 0:
-      print 'Error: Did not successfully install msr-tools.'
+      print('Error: Did not successfully install msr-tools.')
       return False
 
-  print 'Running setcap on %s.' % RDMSR_PATH
+  print('Running setcap on %s.' % RDMSR_PATH)
   ret = subprocess.call(['/sbin/setcap', 'cap_sys_rawio+ep', RDMSR_PATH])
   if ret != 0:
-    print 'Error: Cannot give /usr/sbin/rdmsr RAWIO capability.'
+    print('Error: Cannot give /usr/sbin/rdmsr RAWIO capability.')
     return False
 
   return True
@@ -123,21 +124,21 @@
 def main(prog_name, argv):
   if len(argv) == 0:
     if _RunAllChecks():
-      print 'Check succeeded'
+      print('Check succeeded')
       return 0
 
-    print 'Check failed, try running "%s enable" as root to fix.' % prog_name
+    print('Check failed, try running "%s enable" as root to fix.' % prog_name)
     return 1
 
   if len(argv) == 1:
     if argv[0] == 'enable':
       return 0 if _EnableMsr(prog_name) else 1
 
-    print 'Error: Unknown sub-command %s' % argv[0]
+    print('Error: Unknown sub-command %s' % argv[0])
     _Usage(prog_name)
     return 1
 
-  print 'Error: Bad number of arguments'
+  print('Error: Bad number of arguments')
   _Usage(prog_name)
   return 1
 
diff --git a/telemetry/telemetry/__init__.py b/telemetry/telemetry/__init__.py
index ff7225b..e2addd7 100644
--- a/telemetry/telemetry/__init__.py
+++ b/telemetry/telemetry/__init__.py
@@ -2,6 +2,12 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 """A library for cross-platform browser tests."""
+
+# For some reason pylint thinks this import is at wrong position
+# pylint: disable=wrong-import-position
+from __future__ import print_function
+# pylint: enable=wrong-import-position
+
 import os
 import sys
 
@@ -14,7 +20,7 @@
 
 # Ensure Python >= 2.7.
 if sys.version_info < (2, 7):
-  print >> sys.stderr, 'Need Python 2.7 or greater.'
+  print('Need Python 2.7 or greater.', file=sys.stderr)
   sys.exit(-1)
 
 
diff --git a/telemetry/telemetry/command_line/commands.py b/telemetry/telemetry/command_line/commands.py
index 4266f97..99a6f96 100644
--- a/telemetry/telemetry/command_line/commands.py
+++ b/telemetry/telemetry/command_line/commands.py
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 """Defines the commands provided by Telemetry: Run, List."""
 
+from __future__ import print_function
 import json
 import logging
 import optparse
@@ -96,9 +97,9 @@
     output_pipe = sys.stdout
 
   if not benchmarks:
-    print >> output_pipe, 'No benchmarks found!'
+    print('No benchmarks found!', file=output_pipe)
     if json_pipe:
-      print >> json_pipe, '[]'
+      print('[]', file=json_pipe)
     return
 
   bad_benchmark = next((b for b in benchmarks
@@ -125,25 +126,27 @@
 
   supported = [b for b in all_benchmark_info if b['supported']]
   if supported:
-    print >> output_pipe, 'Available benchmarks %sare:' % (
-        'for %s ' % possible_browser.browser_type if possible_browser else '')
+    browser_type_msg = \
+      ('for %s ' % possible_browser.browser_type if possible_browser else '')
+    print('Available benchmarks %sare:' % browser_type_msg, file=output_pipe)
     for b in supported:
-      print >> output_pipe, format_string % (b['name'], b['description'])
+      print(format_string % (b['name'], b['description']), file=output_pipe)
 
   not_supported = [b for b in all_benchmark_info if not b['supported']]
   if not_supported:
-    print >> output_pipe, (
-        '\nNot supported benchmarks for %s are (force run with -d):' %
-        possible_browser.browser_type)
+    print(('\nNot supported benchmarks for %s are (force run with -d):' %
+           possible_browser.browser_type),
+          file=output_pipe)
     for b in not_supported:
-      print >> output_pipe, format_string % (b['name'], b['description'])
+      print(format_string % (b['name'], b['description']), file=output_pipe)
 
-  print >> output_pipe, (
-      'Pass --browser to list benchmarks for another browser.\n')
+  print('Pass --browser to list benchmarks for another browser.\n',
+        file=output_pipe)
 
   if json_pipe:
-    print >> json_pipe, json.dumps(all_benchmark_info, indent=4,
-                                   sort_keys=True, separators=(',', ': ')),
+    print(json.dumps(all_benchmark_info, indent=4,
+                     sort_keys=True, separators=(',', ': ')),
+          end='', file=json_pipe)
 
 
 class List(object):
@@ -230,7 +233,7 @@
       most_likely_matched_benchmarks = matching.GetMostLikelyMatchedObject(
           all_benchmarks, benchmark_name, lambda x: x.Name())
       if most_likely_matched_benchmarks:
-        print >> sys.stderr, 'Do you mean any of those benchmarks below?'
+        print('Do you mean any of those benchmarks below?', file=sys.stderr)
         PrintBenchmarkList(most_likely_matched_benchmarks, None, sys.stderr)
       parser.error('no such benchmark: %s' % benchmark_name)
 
diff --git a/telemetry/telemetry/core/local_server.py b/telemetry/telemetry/core/local_server.py
index c441be8..7423032 100644
--- a/telemetry/telemetry/core/local_server.py
+++ b/telemetry/telemetry/core/local_server.py
@@ -4,6 +4,7 @@
 
 # TODO(aiolos): this should be moved to catapult/base after the repo move.
 # It is used by tracing in tvcm/browser_controller.
+from __future__ import print_function
 import collections
 import json
 import logging
@@ -102,7 +103,7 @@
     # TODO: This will hang if the subprocess doesn't print the correct output.
     while self._subprocess.poll() is None:
       line = self._subprocess.stdout.readline()
-      print line
+      print(line)
       m = named_ports_re.match(line)
       if m:
         named_ports_json = m.group('port')
@@ -237,8 +238,8 @@
   # Note: This message is scraped by the parent process'
   # _GetNamedPortsFromBackend(). Do **not** change it.
   # pylint: disable=protected-access
-  print 'LocalServerBackend started: %s' % json.dumps([pair._asdict()
-                                                       for pair in named_ports])
+  print('LocalServerBackend started: %s' %
+        json.dumps([pair._asdict() for pair in named_ports]))
   sys.stdout.flush()
 
   return server.ServeForever()
diff --git a/telemetry/telemetry/core/memory_cache_http_server.py b/telemetry/telemetry/core/memory_cache_http_server.py
index 0967e3c..9aa0713 100644
--- a/telemetry/telemetry/core/memory_cache_http_server.py
+++ b/telemetry/telemetry/core/memory_cache_http_server.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 import BaseHTTPServer
 from collections import namedtuple
 import errno
@@ -251,7 +252,7 @@
     paths = args['paths']
     for path in paths:
       if not os.path.realpath(path).startswith(os.path.realpath(os.getcwd())):
-        print >> sys.stderr, '"%s" is not under the cwd.' % path
+        print('"%s" is not under the cwd.' % path, file=sys.stderr)
         sys.exit(1)
 
     server_address = (args['host'], args['port'])
diff --git a/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py b/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py
index 8c39d67..db9e177 100644
--- a/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py
+++ b/telemetry/telemetry/internal/backends/chrome/desktop_browser_backend.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 import datetime
 import hashlib
 import logging
@@ -203,7 +204,7 @@
         # This can happen in the case that loading the Chrome binary fails.
         # We print rather than using logging here, because that makes a
         # recursive call to this function.
-        print >> sys.stderr, "Can't get standard output with --show-stdout"
+        print("Can't get standard output with --show-stdout", file=sys.stderr)
       return ''
     self._tmp_output_file.flush()
     try:
diff --git a/telemetry/telemetry/internal/backends/chrome/lacros_browser_backend.py b/telemetry/telemetry/internal/backends/chrome/lacros_browser_backend.py
index f5802b1..4a63b04 100644
--- a/telemetry/telemetry/internal/backends/chrome/lacros_browser_backend.py
+++ b/telemetry/telemetry/internal/backends/chrome/lacros_browser_backend.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 import logging
 import shutil
 import thread
@@ -139,7 +140,7 @@
     self._is_browser_running = self._IsDevtoolsUp()
     # TODO(crbug/1150455) - Find another condtion to wait on.
     time.sleep(1)
-    print 'Is Lacros up? ' + str(self._is_browser_running)
+    print('Is Lacros up? ' + str(self._is_browser_running))
 
   def Start(self, startup_args):
     self._cri.OpenConnection()
diff --git a/telemetry/telemetry/internal/browser/browser_options.py b/telemetry/telemetry/internal/browser/browser_options.py
index b53c896..c8dc65d 100644
--- a/telemetry/telemetry/internal/browser/browser_options.py
+++ b/telemetry/telemetry/internal/browser/browser_options.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 import atexit
 import copy
 import logging
@@ -351,9 +352,9 @@
         if binary_manager.NeedsInit():
           binary_manager.InitDependencyManager([])
         devices = device_finder.GetDevicesMatchingOptions(self)
-        print 'Available devices:'
+        print('Available devices:')
         for device in devices:
-          print ' ', device.name
+          print(' ', device.name)
         sys.exit(0)
 
       if self.browser_executable and not self.browser_type:
@@ -372,17 +373,17 @@
             browser_types[device.name] = sorted(
                 [browser.browser_type for browser in possible_browsers])
           except browser_finder_exceptions.BrowserFinderException as ex:
-            print >> sys.stderr, 'ERROR: ', ex
+            print('ERROR: ', ex, file=sys.stderr)
             sys.exit(1)
-        print 'Available browsers:'
+        print('Available browsers:')
         if len(browser_types) == 0:
-          print '  No devices were found.'
+          print('  No devices were found.')
         for device_name in sorted(browser_types.keys()):
-          print '  ', device_name
+          print('  ', device_name)
           for browser_type in browser_types[device_name]:
-            print '    ', browser_type
+            print('    ', browser_type)
           if len(browser_types[device_name]) == 0:
-            print '     No browsers found for this device'
+            print('     No browsers found for this device')
         sys.exit(0)
 
       if ((self.browser_type == 'cros-chrome' or
@@ -402,7 +403,7 @@
       # incorrect profiles so this will not be supported.
       if (len(self.interval_profiling_periods) > 1
           and 'story_run' in self.interval_profiling_periods):
-        print 'Cannot specify other periods along with the story_run period.'
+        print('Cannot specify other periods along with the story_run period.')
         sys.exit(1)
 
       self.interval_profiler_options = shlex.split(
diff --git a/telemetry/telemetry/internal/platform/posix_platform_backend.py b/telemetry/telemetry/internal/platform/posix_platform_backend.py
index c41e9d7..7bdccdc 100644
--- a/telemetry/telemetry/internal/platform/posix_platform_backend.py
+++ b/telemetry/telemetry/internal/platform/posix_platform_backend.py
@@ -4,6 +4,7 @@
 
 # pylint: disable=import-error
 # pylint: disable=no-name-in-module
+from __future__ import print_function
 import distutils.spawn as spawn
 import logging
 import os
@@ -97,11 +98,11 @@
               'for a prompt. Please ask an administrator to set the setuid '
               'bit on this executable and ensure that it is owned by a user '
               'with the necessary privileges. Aborting.' % application)
-          print text
+          print(text)
           raise Exception(text)
         # Else, there is a tty that can be used for a useful interactive prompt.
-        print ('Telemetry needs to run %s under sudo. Please authenticate.' %
-               application)
+        print('Telemetry needs to run %s under sudo. Please authenticate.' %
+              application)
         # Synchronously authenticate.
         subprocess.check_call(['/usr/bin/sudo', '-v'])
 
diff --git a/telemetry/telemetry/internal/snap_page_util.py b/telemetry/telemetry/internal/snap_page_util.py
index a024b2b..64d6abc 100644
--- a/telemetry/telemetry/internal/snap_page_util.py
+++ b/telemetry/telemetry/internal/snap_page_util.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 import codecs
 import os
 import logging
@@ -92,16 +93,16 @@
     try:
       image_request = urllib2.urlopen(image_url)
     except IOError as e:
-      print 'Error fetching image [local_file=%s, url=%s, message=%s].' % (
-          image_file, image_url, e)
+      print('Error fetching image [local_file=%s, url=%s, message=%s].' % (
+          image_file, image_url, e))
       continue
 
     try:
       with open(image_file, 'wb') as image_file_handle:
         shutil.copyfileobj(BytesIO(image_request.read()), image_file_handle)
     except IOError as e:
-      print 'Error copying image [local_file=%s, url=%s, message=%s].' % (
-          image_file, image_url, e)
+      print('Error copying image [local_file=%s, url=%s, message=%s].' % (
+          image_file, image_url, e))
 
 def _GetLocalImageDirectory(snapshot_path):
   return os.path.splitext(snapshot_path)[0]
@@ -119,7 +120,7 @@
           'Activating interactive mode. Press enter after you finish '
           "interacting with the page to snapshot the page's DOM content.")
 
-    print 'Snapshotting content of %s. This could take a while...' % url
+    print('Snapshotting content of %s. This could take a while...' % url)
     tab.WaitForDocumentReadyStateToBeComplete()
     tab.action_runner.WaitForNetworkQuiescence(
         timeout_in_seconds=EXPENSIVE_JS_TIMEOUT_SECONDS)
@@ -184,7 +185,7 @@
     page_snapshot = tab.EvaluateJavaScript('outputHTMLString(serializedDoms);',
                                            timeout=EXPENSIVE_JS_TIMEOUT_SECONDS)
 
-    print 'Writing page snapshot [path=%s].' % snapshot_path
+    print('Writing page snapshot [path=%s].' % snapshot_path)
     snapshot_file.write(page_snapshot)
     for i in xrange(len(external_images)):
       _FetchImages(image_dir, i, external_images[i])
@@ -203,4 +204,4 @@
   with codecs.open(snapshot_path, 'w', 'utf-8') as f:
     _SnapPageToFile(finder_options, url, interactive, snapshot_path, f,
                     enable_browser_log)
-  print 'Successfully saved snapshot to file://%s' % snapshot_path
+  print('Successfully saved snapshot to file://%s' % snapshot_path)
diff --git a/telemetry/telemetry/internal/story_runner.py b/telemetry/telemetry/internal/story_runner.py
index 6656b1b..b531e69 100644
--- a/telemetry/telemetry/internal/story_runner.py
+++ b/telemetry/telemetry/internal/story_runner.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 import contextlib
 import itertools
 import logging
@@ -254,7 +255,7 @@
   if finder_options.print_only:
     if finder_options.print_only == 'tags':
       tags = set(itertools.chain.from_iterable(s.tags for s in stories))
-      print 'List of tags:\n%s' % '\n'.join(tags)
+      print('List of tags:\n%s' % '\n'.join(tags))
       return
     include_tags = finder_options.print_only == 'both'
     if include_tags:
@@ -262,7 +263,7 @@
     else:
       format_string = '%s%s'
     for s in stories:
-      print format_string % (s.name, ','.join(s.tags) if include_tags else '')
+      print(format_string % (s.name, ','.join(s.tags) if include_tags else ''))
     return
 
   if (not finder_options.use_live_sites and
@@ -381,9 +382,9 @@
     return True  # Should always run on print-only mode.
   if benchmark.CanRunOnPlatform(possible_browser.platform, finder_options):
     return True
-  print ('Benchmark "%s" is not supported on the current platform. If this '
-         "is in error please add it to the benchmark's SUPPORTED_PLATFORMS."
-         % benchmark.Name())
+  print('Benchmark "%s" is not supported on the current platform. If this '
+        "is in error please add it to the benchmark's SUPPORTED_PLATFORMS."
+        % benchmark.Name())
   return False
 
 
@@ -400,7 +401,7 @@
 
   possible_browser = browser_finder.FindBrowser(finder_options)
   if not possible_browser:
-    print ('No browser of type "%s" found for running benchmark "%s".' % (
+    print('No browser of type "%s" found for running benchmark "%s".' % (
         finder_options.browser_options.browser_type, benchmark.Name()))
     return exit_codes.ALL_TESTS_SKIPPED
 
diff --git a/telemetry/telemetry/internal/testing/dependency_test_dir/other_animals/cat/cat/cat_object.py b/telemetry/telemetry/internal/testing/dependency_test_dir/other_animals/cat/cat/cat_object.py
index 41be7ba..70de262 100644
--- a/telemetry/telemetry/internal/testing/dependency_test_dir/other_animals/cat/cat/cat_object.py
+++ b/telemetry/telemetry/internal/testing/dependency_test_dir/other_animals/cat/cat/cat_object.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 class Cat(object):
   def Run(self):
-    print 'Meow'
+    print('Meow')
diff --git a/telemetry/telemetry/internal/testing/dependency_test_dir/other_animals/moose/moose/moose_object.py b/telemetry/telemetry/internal/testing/dependency_test_dir/other_animals/moose/moose/moose_object.py
index 1e87ea4..9e15553 100644
--- a/telemetry/telemetry/internal/testing/dependency_test_dir/other_animals/moose/moose/moose_object.py
+++ b/telemetry/telemetry/internal/testing/dependency_test_dir/other_animals/moose/moose/moose_object.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 from horn import horn_object  # pylint: disable=relative-import
 
 class Moose(object):
@@ -10,4 +11,4 @@
 
   def Run(self):
     if self._horn.IsBig():
-      print 'I need to drop my horn! It is big!'
+      print('I need to drop my horn! It is big!')
diff --git a/telemetry/telemetry/internal/util/binary_manager.py b/telemetry/telemetry/internal/util/binary_manager.py
index 5c61956..5e1e629 100644
--- a/telemetry/telemetry/internal/util/binary_manager.py
+++ b/telemetry/telemetry/internal/util/binary_manager.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 import contextlib
 import logging
 import os
@@ -257,7 +258,7 @@
   c = base_config.BaseConfig(config, writable=True)
   try:
     old_version = c.GetVersion(dependency, dep_platform)
-    print 'Updating from version: {}'.format(old_version)
+    print('Updating from version: {}'.format(old_version))
   except ValueError:
     raise RuntimeError(
         ('binary_dependencies.json entry for %s missing or invalid; please add '
diff --git a/telemetry/telemetry/internal/util/exception_formatter.py b/telemetry/telemetry/internal/util/exception_formatter.py
index fe036c8..55aade4 100644
--- a/telemetry/telemetry/internal/util/exception_formatter.py
+++ b/telemetry/telemetry/internal/util/exception_formatter.py
@@ -4,6 +4,7 @@
 
 """Print prettier and more detailed exceptions."""
 
+from __future__ import print_function
 import logging
 import math
 import os
@@ -37,8 +38,8 @@
   exception_string = '\n'.join(l.strip() for l in exception_list)
 
   if msg:
-    print >> sys.stderr
-    print >> sys.stderr, msg
+    print(file=sys.stderr)
+    print(msg, file=sys.stderr)
 
   _PrintFormattedTrace(processed_tb, frame, exception_string)
 
@@ -54,24 +55,24 @@
     - Report stacks to maintainers like depot_tools does.
     - Add a debug flag to automatically start pdb upon exception.
   """
-  print >> sys.stderr
+  print(file=sys.stderr)
 
   # Format the traceback.
-  print >> sys.stderr, 'Traceback (most recent call last):'
+  print('Traceback (most recent call last):', file=sys.stderr)
   for filename, line, function, text in processed_tb:
     filename = os.path.abspath(filename)
-    print >> sys.stderr, '  %s at %s:%d' % (function, filename, line)
-    print >> sys.stderr, '    %s' % text
+    print('  %s at %s:%d' % (function, filename, line), file=sys.stderr)
+    print('    %s' % text, file=sys.stderr)
 
   # Format the exception.
   if exception_string:
-    print >> sys.stderr, exception_string
+    print(exception_string, file=sys.stderr)
 
   # Format the locals.
   local_variables = [(variable, value) for variable, value in
                      frame.f_locals.iteritems() if variable != 'self']
-  print >> sys.stderr
-  print >> sys.stderr, 'Locals:'
+  print(file=sys.stderr)
+  print('Locals:', file=sys.stderr)
   if local_variables:
     longest_variable = max(len(v) for v, _ in local_variables)
     for variable, value in sorted(local_variables):
@@ -80,13 +81,14 @@
       truncation_indication = ''
       if len(possibly_truncated_value) != len(value):
         truncation_indication = ' (truncated)'
-      print >> sys.stderr, '  %s: %s%s' % (variable.ljust(longest_variable + 1),
-                                           possibly_truncated_value,
-                                           truncation_indication)
+      print('  %s: %s%s' % (variable.ljust(longest_variable + 1),
+                            possibly_truncated_value,
+                            truncation_indication),
+            file=sys.stderr)
   else:
-    print >> sys.stderr, '  No locals!'
+    print('  No locals!', file=sys.stderr)
 
-  print >> sys.stderr
+  print(file=sys.stderr)
   sys.stderr.flush()
 
 
diff --git a/telemetry/telemetry/internal/util/external_modules.py b/telemetry/telemetry/internal/util/external_modules.py
index de09561..9df166d 100644
--- a/telemetry/telemetry/internal/util/external_modules.py
+++ b/telemetry/telemetry/internal/util/external_modules.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 import importlib
 import logging
 
@@ -56,7 +57,7 @@
     # the implementation. It's important to re-raise the error here
     # instead of failing silently.
     if 'cannot import name' in str(e):
-      print 'Possible circular dependency!'
+      print('Possible circular dependency!')
       raise
     logging.warning('Unable to import %s due to: %s', module, e)
     return None
diff --git a/telemetry/telemetry/testing/browser_test_runner.py b/telemetry/telemetry/testing/browser_test_runner.py
index 4acbe01..5e94ce0 100644
--- a/telemetry/telemetry/testing/browser_test_runner.py
+++ b/telemetry/telemetry/testing/browser_test_runner.py
@@ -1,6 +1,7 @@
 # Copyright 2016 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
+from __future__ import print_function
 import os
 import subprocess
 import sys
@@ -44,9 +45,9 @@
   exit_code = subprocess.call([sys.executable, path_to_run_tests] + args,
                               env=env)
   if exit_code:
-    print '**Non zero exit code**'
-    print ('If you don\'t see any error stack, this could have been a '
-           'native crash. Consider installing faulthandler '
-           '(https://faulthandler.readthedocs.io/) for more useful error '
-           'message')
+    print('**Non zero exit code**')
+    print('If you don\'t see any error stack, this could have been a '
+          'native crash. Consider installing faulthandler '
+          '(https://faulthandler.readthedocs.io/) for more useful error '
+          'message')
   return exit_code
diff --git a/telemetry/telemetry/testing/run_browser_tests.py b/telemetry/telemetry/testing/run_browser_tests.py
index 746892c..7b3a215 100644
--- a/telemetry/telemetry/testing/run_browser_tests.py
+++ b/telemetry/telemetry/testing/run_browser_tests.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 import os
 import sys
 import json
@@ -23,7 +24,7 @@
   options = browser_options.BrowserFinderOptions()
   options.browser_type = 'any'
   parser = options.CreateParser()
-  print '\n\nCommand line arguments handled by Telemetry:'
+  print('\n\nCommand line arguments handled by Telemetry:')
   parser.print_help()
 
 
@@ -88,9 +89,9 @@
       shard_time = 0.0
       for t in s:
         shard_time += _TestTime(t, test_times, median)
-      print 'shard %d: %d seconds (%d tests)' % (i, shard_time, num_tests)
+      print('shard %d: %d seconds (%d tests)' % (i, shard_time, num_tests))
     else:
-      print 'shard %d: %d tests (unknown duration)' % (i, num_tests)
+      print('shard %d: %d tests (unknown duration)' % (i, num_tests))
 
 
 def _SplitShardsByTime(test_cases, total_shards, test_times,
@@ -241,9 +242,9 @@
       break
 
   if not test_class:
-    print 'Cannot find test class with name matching %s' % options.test
-    print 'Available tests: %s' % '\n'.join(
-        cl.Name() for cl in browser_test_classes)
+    print('Cannot find test class with name matching %s' % options.test)
+    print('Available tests: %s' % '\n'.join(
+        cl.Name() for cl in browser_test_classes))
     return 1
 
   test_class._typ_runner = typ_runner = typ.Runner()
@@ -330,7 +331,7 @@
   try:
     ret, _, _ = typ_runner.run()
   except KeyboardInterrupt:
-    print >> sys.stderr, "interrupted, exiting"
+    print("interrupted, exiting", file=sys.stderr)
     ret = 130
   return ret
 
diff --git a/telemetry/telemetry/testing/run_tests.py b/telemetry/telemetry/testing/run_tests.py
index be4e686..fc34ad7 100644
--- a/telemetry/telemetry/testing/run_tests.py
+++ b/telemetry/telemetry/testing/run_tests.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 import logging
 import os
 import sys
@@ -171,7 +172,7 @@
       runner.args.jobs = len(android_devs)
       if runner.args.jobs == 0:
         raise RuntimeError("No Android device found")
-      print 'Running tests with %d Android device(s).' % runner.args.jobs
+      print('Running tests with %d Android device(s).' % runner.args.jobs)
     elif platform.GetOSVersionName() == 'xp':
       # For an undiagnosed reason, XP falls over with more parallelism.
       # See crbug.com/388256
@@ -219,7 +220,7 @@
     try:
       ret, _, _ = runner.run()
     except KeyboardInterrupt:
-      print >> sys.stderr, "interrupted, exiting"
+      print("interrupted, exiting", file=sys.stderr)
       ret = 130
     return ret
 
diff --git a/telemetry/telemetry/testing/unittest_runner.py b/telemetry/telemetry/testing/unittest_runner.py
index b9c37ab..e38264f 100644
--- a/telemetry/telemetry/testing/unittest_runner.py
+++ b/telemetry/telemetry/testing/unittest_runner.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
 import os
 import subprocess
 import sys
@@ -51,7 +52,7 @@
   exit_code = subprocess.call([sys.executable, path_to_run_tests] + args,
                               env=env)
   if exit_code:
-    print '**Non zero exit code**'
+    print('**Non zero exit code**')
     print ('If you don\'t see any error stack, this could have been a '
            'native crash. Consider installing faulthandler '
            '(https://faulthandler.readthedocs.io/) for more useful error '
diff --git a/telemetry/third_party/altgraph/altgraph/ObjectGraph.py b/telemetry/third_party/altgraph/altgraph/ObjectGraph.py
index d07f51b..c77768e 100644
--- a/telemetry/third_party/altgraph/altgraph/ObjectGraph.py
+++ b/telemetry/third_party/altgraph/altgraph/ObjectGraph.py
@@ -6,6 +6,7 @@
 graphident is the key for the object in the graph
 """
 
+from __future__ import print_function
 from altgraph import GraphError
 from altgraph.Graph import Graph
 from altgraph.GraphUtil import filter_stack
diff --git a/telemetry/third_party/altgraph/setup.py b/telemetry/third_party/altgraph/setup.py
index a1a4cb6..7867056 100644
--- a/telemetry/third_party/altgraph/setup.py
+++ b/telemetry/third_party/altgraph/setup.py
@@ -15,6 +15,7 @@
 
 """
 
+from __future__ import print_function
 import sys
 import os
 import re
diff --git a/telemetry/third_party/modulegraph/modulegraph_tests/test_import_from_init.py b/telemetry/third_party/modulegraph/modulegraph_tests/test_import_from_init.py
index f1333a1..d458a00 100644
--- a/telemetry/third_party/modulegraph/modulegraph_tests/test_import_from_init.py
+++ b/telemetry/third_party/modulegraph/modulegraph_tests/test_import_from_init.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import sys
 if sys.version_info[:2] <= (2,6):
     import unittest2 as unittest
diff --git a/telemetry/third_party/modulegraph/modulegraph_tests/test_imports.py b/telemetry/third_party/modulegraph/modulegraph_tests/test_imports.py
index 8cdcfa7..b72cb19 100644
--- a/telemetry/third_party/modulegraph/modulegraph_tests/test_imports.py
+++ b/telemetry/third_party/modulegraph/modulegraph_tests/test_imports.py
@@ -1,6 +1,7 @@
 """
 Test for import machinery
 """
+from __future__ import print_function
 import unittest
 import sys
 import textwrap
diff --git a/telemetry/third_party/modulegraph/modulegraph_tests/test_pep420_nspkg.py b/telemetry/third_party/modulegraph/modulegraph_tests/test_pep420_nspkg.py
index a20c981..e5a1fa2 100644
--- a/telemetry/third_party/modulegraph/modulegraph_tests/test_pep420_nspkg.py
+++ b/telemetry/third_party/modulegraph/modulegraph_tests/test_pep420_nspkg.py
@@ -3,6 +3,7 @@
 
 PEP 420 is new in Python 3.3
 """
+from __future__ import print_function
 import os
 import shutil
 import sys
diff --git a/telemetry/third_party/modulegraph/modulegraph_tests/test_setuptools_nspkg.py b/telemetry/third_party/modulegraph/modulegraph_tests/test_setuptools_nspkg.py
index 87f845c..f66e30d 100644
--- a/telemetry/third_party/modulegraph/modulegraph_tests/test_setuptools_nspkg.py
+++ b/telemetry/third_party/modulegraph/modulegraph_tests/test_setuptools_nspkg.py
@@ -3,6 +3,7 @@
 packages, and in particular the installation
 flavour used by pip
 """
+from __future__ import print_function
 import os
 import shutil
 import sys
diff --git a/telemetry/third_party/modulegraph/modulegraph_tests/testdata/nspkg/src/install.py b/telemetry/third_party/modulegraph/modulegraph_tests/testdata/nspkg/src/install.py
index 3f14e73..a57a0d5 100644
--- a/telemetry/third_party/modulegraph/modulegraph_tests/testdata/nspkg/src/install.py
+++ b/telemetry/third_party/modulegraph/modulegraph_tests/testdata/nspkg/src/install.py
@@ -6,6 +6,7 @@
 Use this script with new versions of distribute and setuptools to ensure
 that changes in the handling of this option don't break us.
 """
+from __future__ import print_function
 import pkg_resources
 import subprocess
 import os
diff --git a/telemetry/third_party/modulegraph/scripts/extract_implies.py b/telemetry/third_party/modulegraph/scripts/extract_implies.py
index d6ab353..3e359e8 100644
--- a/telemetry/third_party/modulegraph/scripts/extract_implies.py
+++ b/telemetry/third_party/modulegraph/scripts/extract_implies.py
@@ -9,6 +9,7 @@
 this information.
 """
 
+from __future__ import print_function
 import re
 import sys
 import os
@@ -37,7 +38,7 @@
 
 def main():
     for version in ('2.6', '2.7', '3.1'):
-        print "====", version
+        print("====", version)
         pprint.pprint(list(extract_implies('/Users/ronald/Projects/python/release%s-maint'%(version.replace('.', '')))))
 
 if __name__ == "__main__":
diff --git a/telemetry/third_party/modulegraph/setup.py b/telemetry/third_party/modulegraph/setup.py
index a1a4cb6..7867056 100644
--- a/telemetry/third_party/modulegraph/setup.py
+++ b/telemetry/third_party/modulegraph/setup.py
@@ -15,6 +15,7 @@
 
 """
 
+from __future__ import print_function
 import sys
 import os
 import re
diff --git a/telemetry/third_party/png/png.py b/telemetry/third_party/png/png.py
index b55dd3a..5fb857e 100755
--- a/telemetry/third_party/png/png.py
+++ b/telemetry/third_party/png/png.py
@@ -165,6 +165,7 @@
 # http://www.python.org/doc/2.2.3/whatsnew/node5.html
 from __future__ import generators
 
+from __future__ import print_function
 __version__ = "$URL$ $Rev$"
 
 from array import array
@@ -2444,7 +2445,7 @@
 
     import os
 
-    print name
+    print(name)
     f = BytesIO()
     w = Writer(x, y, **k)
     w.write(f, rows)
@@ -2608,7 +2609,7 @@
             candi = candidate.replace('n', 'i')
             if candi not in _pngsuite:
                 continue
-            print 'adam7 read', candidate
+            print('adam7 read', candidate)
             straight = Reader(bytes=_pngsuite[candidate])
             adam7 = Reader(bytes=_pngsuite[candi])
             # Just compare the pixels.  Ignore x,y (because they're
@@ -2882,7 +2883,7 @@
         try:
             import numpy
         except ImportError:
-            print >>sys.stderr, "skipping numpy test"
+            print("skipping numpy test", file=sys.stderr)
             return
 
         rows = [map(numpy.uint16, range(0,0x10000,0x5555))]
@@ -2894,7 +2895,7 @@
         try:
             import numpy
         except ImportError:
-            print >>sys.stderr, "skipping numpy test"
+            print("skipping numpy test", file=sys.stderr)
             return
 
         rows = [map(numpy.uint8, range(0,0x100,0x55))]
@@ -2906,7 +2907,7 @@
         try:
             import numpy
         except ImportError:
-            print >>sys.stderr, "skipping numpy test"
+            print("skipping numpy test", file=sys.stderr)
             return
 
         rows = [map(numpy.bool, [0,1])]
@@ -2917,7 +2918,7 @@
         try:
             import numpy
         except ImportError:
-            print >>sys.stderr, "skipping numpy test"
+            print("skipping numpy test", file=sys.stderr)
             return
 
         pixels = numpy.array([[0,0x5555],[0x5555,0xaaaa]], numpy.uint16)
@@ -3854,4 +3855,4 @@
     try:
         _main(sys.argv)
     except Error, e:
-        print >>sys.stderr, e
+        print(e, file=sys.stderr)
diff --git a/telemetry/third_party/websocket-client/bin/wsdump.py b/telemetry/third_party/websocket-client/bin/wsdump.py
index e06271c..1eaaeec 100755
--- a/telemetry/third_party/websocket-client/bin/wsdump.py
+++ b/telemetry/third_party/websocket-client/bin/wsdump.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 
+from __future__ import print_function
 import argparse
 import code
 import sys
diff --git a/telemetry/third_party/websocket-client/compliance/test_fuzzingclient.py b/telemetry/third_party/websocket-client/compliance/test_fuzzingclient.py
index f4b0ff1..d8a56ce 100644
--- a/telemetry/third_party/websocket-client/compliance/test_fuzzingclient.py
+++ b/telemetry/third_party/websocket-client/compliance/test_fuzzingclient.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 
+from __future__ import print_function
 import json
 import traceback
 
diff --git a/telemetry/third_party/websocket-client/examples/echoapp_client.py b/telemetry/third_party/websocket-client/examples/echoapp_client.py
index c15b35f..7080275 100644
--- a/telemetry/third_party/websocket-client/examples/echoapp_client.py
+++ b/telemetry/third_party/websocket-client/examples/echoapp_client.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 import websocket
 try:
     import thread