Передача очень длинного списка как sys.argv (pvpython в python) - PullRequest
0 голосов
/ 17 апреля 2019

Ошибка:

OSError: [Errno 7] Список аргументов слишком длинный

История:

Запуск сценария на pvpython (vtk); однако в более старых дистрибутивах pvpython <5.0 модули matplotlib устарели, поэтому использование этого модуля невозможно. Чтобы преодолеть это, используется еще один <code>.py и аргументы, передаваемые в терминале с использованием subprocess, как показано ниже, и выполняются на python , но поскольку передаваемая информация велика, вышеприведенный ошибка встречается

Проблемный код:

import subprocess
command = ("python illustrations.py %s %s %s %s %s %s %s %s %s %s" % (str(post_processing), str(width), str(height), str(len(new_overall_lines)), str(reset_scale), str(str_rose_angle), str(str_damage), str(fname), str(fname1), str("ax=None")))
subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)

argv 6 и 7 являются чрезвычайно длинными (882770, 879326) символами каждый, поскольку они являются списками.

Альтернативным решением может быть передача списка во временный файл и загрузка его в модуль python. Но я пытаюсь сэкономить на записи и времени загрузки.

Таким образом, я ищу способ передачи больших аргументов в терминале или как передать аргументы двум средам, в данном случае pvpython и python.

1 Ответ

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

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

Итак, не используйте shell=True (что не рекомендуется использовать специально по этой причине!) и вызывайте вашу программу через правильный список аргументов:

command = ["python", "illustrations.py"] +
          [str(v) for v in post_processing, width, height,
                            len(new_overall_lines), reset_scale,
                            str_rose_angle, str_damage,
                            fname, fname1] +
          ["ax=None"]

subprocess.Popen(command, stdout=subprocess.PIPE)

Кроме того, и поскольку передача командной строки зависит от ОС (например, в Windows ваш массив все равно будет объединен в одну строку под капотом, потому что именно так CreateProcess требует передачи командной строки) и На отдельные аргументы командной строки также распространяются ограничения на длину , . Лучшее решение - передавать произвольно длинные данные с помощью средств, отличных от командной строки.

Существуют следующие способы передачи информации дочернему процессу:

  • Командная строка
  • файлы (поскольку файловая система является общим ресурсом, с учетом требований защиты от других процессов )
  • IPC (каналы, включая стандартные потоки, общую память, сокеты и т. Д.)
  • вещи, унаследованные через fork():
    • снимок памяти (применяется только в том случае, если ребенок запускает ту же программу)
    • дескрипторы (сюда также попадают стандартные потоки; обратите внимание, что Python намеренно помечает дескрипторы файлов, отличные от стандартных потоков, которые не наследуются по умолчанию)
    • переменные окружения

Как видите, параметры командной строки далеко не единственные.

...