Pip install upgrade не может удалить временные файлы - PullRequest
0 голосов
/ 23 апреля 2019

В ходе обслуживания утилиты CLI я хочу добавить действие update, которое будет извлекать последнюю версию этого пакета из PyPI и обновлять существующую установку.

$ cli -V
1.0.23

$ cli update
// many lines of pip spam

$ cli -V
1.0.24  // or etc

Это прекрасно работает на всех машинах, на которых установлен Python для всей системы (в C:\Python36 или аналогичных), но машины, на которых установлен Python как пользователь (в C:\users\username\AppData\Local\Programs\Python\Python36), получают эту ошибку, так как старая версия удаляется :

Could not install packages due to an EnvironmentError: [WinError 5] Access is denied: 'C:\\Users\\username\\AppData\\Local\\Temp\\pip-uninstall-f5a7rk2y\\cli.exe'
Consider using the `--user` option or check the permissions.

Я предполагал, что это связано с тем, что cli.exe, вызванный в тексте ошибки, в данный момент выполняется, когда pip пытается его удалить, однако путь здесь не к %LOCALAPPDATA%\Programs\Python\Python36\Scripts, где живет этот exe, но вместо %TEMP%. Как можно переместить файл туда, но не удалить его, когда он там будет?

, включая --user в установочных аргументах, как рекомендовано в сообщении об ошибке, не (вопреки указанию на более раннее редактирование этого вопроса) решает проблему, но перемещается cli исполняемый файл в другом месте делает.

Я надеюсь получить ответ, который:

  1. Объясняет причину неудачной попытки удалить исполняемый файл из каталога TEMP и ...
  2. Предоставляет решение этой проблемы, чтобы обойти ошибку разрешений или запросить, установлен ли этот пакет как пользователь, чтобы код мог добавить --user к аргументам.

Хотя вопрос довольно общий, MCVE ниже:

def update(piphost):
    args = ['pip', 'install',
        '--index-url', piphost,
        '-U', 'cli']
    subprocess.check_call(args)

update('https://mypypiserver:8001')

1 Ответ

0 голосов
/ 24 апреля 2019

Как первоначально предполагалось, проблема здесь заключалась в попытке удалить работающий исполняемый файл.Windows не фанат такой ерунды и выдает PermissionErrors при попытке.Любопытно, что вы, безусловно, можете переименовать запущенный исполняемый файл, и фактически несколько вопросов из различных тегов useэтот факт допускает явное изменение к исполняемому исполняемому файлу.

Это также объясняет, почему исполняемый файл, по-видимому, работает с %LOCALAPPDATA%\Programs\Python\Python36\Scripts, но не удаляется из %TEMP%.Он был переименован (перемещен) в папку %TEMP% во время выполнения (что является законным), а затем pip пытается удалить этот каталог, также удаляя этот файл (что является недопустимым).

Реализация идет так:

  1. Переименовать текущий исполняемый файл (Path(sys.argv[0]).with_suffix('.exe'))
  2. pip install, чтобы обновить пакет
  3. Добавить логику в вашу точку входа, которая удаляет переименованный исполняемый файл, если онсуществует.
import click  # I'm using click for my CLI, but YMMV
from pathlib import Path
from sys import argv

def entrypoint():
    # setup.py's console_scripts points cli.exe to here

    tmp_exe_path = Path(argv[0]).with_suffix('.tmp')
    try:
        tmp_exe_path.unlink()
    except FileNotFoundError:
        pass
    return cli_root

@click.group()
def cli_root():
    pass

def update(pip_host):

    exe_path = Path(argv[0])
    tmp_exe_path = exe_path.with_suffix('.tmp')
    handle_renames = False
    if exe_path.with_suffix('.exe').exists():
        # we're running on Windows, so we have to deal with this tomfoolery.
        handle_renames = True
        exe_path.rename(tmp_exe_path)
    args = ['pip', 'install',
        '--index-url', piphost,
        '-U', 'cli']
    try:
        subprocess.check_call(args)
    except Exception:  # in real code you should probably break these out to handle stuff
        if handle_renames:
            tmp_exe_path.rename(exe_path)  # undo the rename if we haven't updated

@cli_root.command('update')
@click.option("--host", default='https://mypypiserver:8001')
def cli_update(host):
    update(host)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...