Исключение Python subprocess.checkoutput () с использованием «журнала svn»

Я столкнулся с проблемой, которую не смог решить.

Я пытаюсь запустить команду subversion через python для обработки результатов. У меня был этот код, запускающий мою систему разработки, но когда я запускаю его в целевой системе, я получаю исключение в модуле подпроцесса.

Почему этот код дает разные результаты на двух моих системах?

command = "svn log --username " + __SVNUSERNAME + " --password " + __SVNPASSWORD + " --no-auth-cache --non-interactive -v -r {2022-09-26}:{2022-09-27} --xml " + __SVNTRUNK
bytes = subprocess.check_output([command], stderr=subprocess.STDOUT,shell=True)

Я получаю следующее исключение:

  File "E:\5_scripts\svn.py", line 89, in __run
    bytes = subprocess.check_output([command], stderr=subprocess.STDOUT,shell=True)
  File "C:\tools\Python3\lib\subprocess.py", line 424, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "C:\tools\Python3\lib\subprocess.py", line 528, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['{command}']' returned non-zero exit status 1.
  1. Я попытался запустить ту же команду subversion в командной строке, и она выполняется так, как я ожидаю. Когда я повторяю %ERRORLEVEL%, он возвращает статус 0. Так что я не понимаю, что происходит по-другому в моей целевой системе.

  2. Я попытался изучить документы python для функции checkoutput(), и, похоже, между 3.6 и 3.9 не было серьезных обновлений.

  3. Я попытался изучить примечания к выпуску подрывной деятельности Apache и не нашел никаких изменений в подкоманде «log».

Система разработки:

  • Линукс 3.10
  • питон 3.6.8
  • свн 1.9.9

Целевая система:

  • Windows-сервер
  • питон 3.9.6
  • свн 1.7.4

🤔 А знаете ли вы, что...
Python поддерживает параллельное и асинхронное программирование с помощью модулей asyncio и multiprocessing.


67
1

Ответ:

Решено

Это потому, что вашей целевой системой является Windows. В частности, shell=True не работает или работает не так, как в Windows, как в Linux. Это имеет некоторый смысл, потому что Windows и Linux имеют разные оболочки (исторически).

Вы можете попробовать следующий код, который должен работать на обеих платформах:

   command = [
      "svn", "log",
      "--username", __SVNUSERNAME,
      "--password",  __SVNPASSWORD,
      "--no-auth-cache", "--non-interactive", "-v", 
      "-r", "{2022-09-26}:{2022-09-27}",
      "--xml",
      __SVNTRUNK
    ]
    
    bytes = subprocess.check_output(command, stderr=subprocess.STDOUT)

Короче говоря, эта версия больше не полагается на оболочку для токенизации командной строки в массив команд, а вместо этого явно создает этот массив. Обратите внимание, что shell=True был удален из вызова check_output().

Это изменение может иметь подводные камни, в частности то, что bash или command.com не будут выполнять какую-либо уникальную для оболочки обработку строки (например, транслитерацию переменных окружения). Не похоже, чтобы ваш предыдущий код полагался на поведение оболочки (кроме токенизации командной строки). Так что это хорошее изменение, поскольку вы поддерживаете две разные среды.


Интересные вопросы для изучения