main.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. """Primary application entrypoint."""
  2. from __future__ import annotations
  3. import locale
  4. import logging
  5. import os
  6. import sys
  7. import warnings
  8. logger = logging.getLogger(__name__)
  9. # Do not import and use main() directly! Using it directly is actively
  10. # discouraged by pip's maintainers. The name, location and behavior of
  11. # this function is subject to change, so calling it directly is not
  12. # portable across different pip versions.
  13. # In addition, running pip in-process is unsupported and unsafe. This is
  14. # elaborated in detail at
  15. # https://pip.pypa.io/en/stable/user_guide/#using-pip-from-your-program.
  16. # That document also provides suggestions that should work for nearly
  17. # all users that are considering importing and using main() directly.
  18. # However, we know that certain users will still want to invoke pip
  19. # in-process. If you understand and accept the implications of using pip
  20. # in an unsupported manner, the best approach is to use runpy to avoid
  21. # depending on the exact location of this entry point.
  22. # The following example shows how to use runpy to invoke pip in that
  23. # case:
  24. #
  25. # sys.argv = ["pip", your, args, here]
  26. # runpy.run_module("pip", run_name="__main__")
  27. #
  28. # Note that this will exit the process after running, unlike a direct
  29. # call to main. As it is not safe to do any processing after calling
  30. # main, this should not be an issue in practice.
  31. def main(args: list[str] | None = None) -> int:
  32. # NOTE: Lazy imports to speed up import of this module,
  33. # which is imported from the pip console script. This doesn't
  34. # speed up normal pip execution, but might be important in the future
  35. # if we use ``multiprocessing`` module,
  36. # which imports __main__ for each spawned subprocess.
  37. from pip._internal.cli.autocompletion import autocomplete
  38. from pip._internal.cli.main_parser import parse_command
  39. from pip._internal.commands import create_command
  40. from pip._internal.exceptions import PipError
  41. from pip._internal.utils import deprecation
  42. if args is None:
  43. args = sys.argv[1:]
  44. # Suppress the pkg_resources deprecation warning
  45. # Note - we use a module of .*pkg_resources to cover
  46. # the normal case (pip._vendor.pkg_resources) and the
  47. # devendored case (a bare pkg_resources)
  48. warnings.filterwarnings(
  49. action="ignore", category=DeprecationWarning, module=".*pkg_resources"
  50. )
  51. # Configure our deprecation warnings to be sent through loggers
  52. deprecation.install_warning_logger()
  53. autocomplete()
  54. try:
  55. cmd_name, cmd_args = parse_command(args)
  56. except PipError as exc:
  57. sys.stderr.write(f"ERROR: {exc}")
  58. sys.stderr.write(os.linesep)
  59. sys.exit(1)
  60. # Needed for locale.getpreferredencoding(False) to work
  61. # in pip._internal.utils.encoding.auto_decode
  62. try:
  63. locale.setlocale(locale.LC_ALL, "")
  64. except locale.Error as e:
  65. # setlocale can apparently crash if locale are uninitialized
  66. logger.debug("Ignoring error %s when setting locale", e)
  67. command = create_command(cmd_name, isolated=("--isolated" in cmd_args))
  68. return command.main(cmd_args)