def install(h, pip, groups, save, save_dev, packages):
    """Install a pip or bower package."""
    if groups:
        groups = [text_type.strip(group) for group in groups.split(",")]
    else:
        groups = h.requirements.keys()

    if not packages:
        for group in groups:
            if group not in h.requirements:
                warning("{} not in requirements".format(group))
                continue
            install = (h.install_bower if group.startswith("bower")
                       else h.install_pip)
            for requirement in h.requirements[group]:
                install(str(requirement), save=False, save_dev=False)
    if pip:
        for package in packages:
            h.install_pip(package, save=save, save_dev=save_dev)
    else:
        for package in packages:
            h.install_bower(package, save=save, save_dev=save_dev)
def log_exception(cls, msg):
        """Try to log an error message to this process's error log and the shared error log.

        NB: Doesn't raise (logs an error instead).
        """
        pid = os.getpid()
        fatal_error_log_entry = cls._format_exception_message(msg, pid)

        # We care more about this log than the shared log, so write to it first.
        try:
            cls._try_write_with_flush(cls._pid_specific_error_fileobj, fatal_error_log_entry)
        except Exception as e:
            logger.error(
                "Error logging the message '{}' to the pid-specific file handle for {} at pid {}:\n{}".format(
                    msg, cls._log_dir, pid, e
                )
            )

        # Write to the shared log.
        try:
            # TODO: we should probably guard this against concurrent modification by other pants
            # subprocesses somehow.
            cls._try_write_with_flush(cls._shared_error_fileobj, fatal_error_log_entry)
        except Exception as e:
            logger.error(
                "Error logging the message '{}' to the shared file handle for {} at pid {}:\n{}".format(
                    msg, cls._log_dir, pid, e
                )
            )