Как развернуть переменную оболочки в подпроцессе xonsh?

#shell #xonsh

Вопрос:

Я учусь ксоншу. Я попробовал следующий простой скрипт, но он не работает zipinfo -1 $mzip_str , особенно при расширении mzip_str .

 #!/usr/bin/env xonsh

from pathlib import Path

my_path = Path('/path/to/downloads/')

dir_list = my_path.glob('*.zip')
for my_zip in dir_list:
  mzip_str = str(my_zip)
  zip_dir_names = $(zipinfo -1 $mzip_str | grep -E '.*/

В оболочке xonsh я получаю следующие результаты:

 ➤ zip_dir_names = $(zipinfo -1 mzip_str)
zipinfo:  cannot find or open mzip_str, mzip_str.zip or mzip_str.ZIP.

➤ zip_dir_names = $(zipinfo -1 $mzip_str)
zipinfo:  cannot find or open $mzip_str, $mzip_str.zip or $mzip_str.ZIP.

➤ zip_dir_names = $(zipinfo -1 @mzip_str)
zipinfo:  cannot find or open @mzip_str, @mzip_str.zip or @mzip_str.ZIP.

➤ zip_dir_names = $(zipinfo -1 !mzip_str)
zipinfo:  cannot find or open mzip_str, mzip_str.zip or mzip_str.ZIP.
 

Ответ №1:

Из официального руководства

Форма @(<expr>) оператора работает в режиме подпроцесса и будет оценивать произвольный код Python. Результат добавляется в список команд подпроцесса. Если результатом является строка или байты, она добавляется в список аргументов. Если результатом является список или другая нестроковая последовательность, содержимое преобразуется в строки и добавляется в список аргументов по порядку. Если результат в первой позиции является функцией, он рассматривается как псевдоним (см. Раздел об псевдонимах ниже), даже если он явно не был добавлен в aliases сопоставление. В противном случае результат автоматически преобразуется в строку.

Таким образом, соответствующая строка должна выглядеть так (непроверено, так как у меня это не xonsh установлено):

 zip_dir_names = $(zipinfo -1 @(my_zip) | grep -E '.*/

Но это звучит так, как будто  $()  возвращает строку, и вы, вероятно, захотите  zip_dir_names  быть списком, если хотите что-то с ним сделать, кроме как распечатать его. Что-то вроде

 zip_dir_names = [ name for name in !(zipinfo -1 @(my_zip)) if name.endsWith("/") ]
 

может сработать лучше. Или, конечно, просто используйте стандартный модуль Python zipfile module вместо внешней программы.

 zip_dir_names = [ f.filename for f in ZipFile(my_zip).infolist() if f.is_dir() ]
 


)
print(zip_dir_names)
В оболочке xonsh я получаю следующие результаты:


Ответ №1:

Из официального руководства

Форма @(<expr>) оператора работает в режиме подпроцесса и будет оценивать произвольный код Python. Результат добавляется в список команд подпроцесса. Если результатом является строка или байты, она добавляется в список аргументов. Если результатом является список или другая нестроковая последовательность, содержимое преобразуется в строки и добавляется в список аргументов по порядку. Если результат в первой позиции является функцией, он рассматривается как псевдоним (см. Раздел об псевдонимах ниже), даже если он явно не был добавлен в aliases сопоставление. В противном случае результат автоматически преобразуется в строку.

Таким образом, соответствующая строка должна выглядеть так (непроверено, так как у меня это не xonsh установлено):


Но это звучит так, как будто $() возвращает строку, и вы, вероятно, захотите zip_dir_names быть списком, если хотите что-то с ним сделать, кроме как распечатать его. Что-то вроде


может сработать лучше. Или, конечно, просто используйте стандартный модуль Python zipfile module вместо внешней программы.


)
Но это звучит так, как будто $() возвращает строку, и вы, вероятно, захотите zip_dir_names быть списком, если хотите что-то с ним сделать, кроме как распечатать его. Что-то вроде


может сработать лучше. Или, конечно, просто используйте стандартный модуль Python zipfile module вместо внешней программы.


)
print(zip_dir_names)В оболочке xonsh я получаю следующие результаты:


Ответ №1:

Из официального руководства

Форма @(<expr>) оператора работает в режиме подпроцесса и будет оценивать произвольный код Python. Результат добавляется в список команд подпроцесса. Если результатом является строка или байты, она добавляется в список аргументов. Если результатом является список или другая нестроковая последовательность, содержимое преобразуется в строки и добавляется в список аргументов по порядку. Если результат в первой позиции является функцией, он рассматривается как псевдоним (см. Раздел об псевдонимах ниже), даже если он явно не был добавлен в aliases сопоставление. В противном случае результат автоматически преобразуется в строку.

Таким образом, соответствующая строка должна выглядеть так (непроверено, так как у меня это не xonsh установлено):


Но это звучит так, как будто $() возвращает строку, и вы, вероятно, захотите zip_dir_names быть списком, если хотите что-то с ним сделать, кроме как распечатать его. Что-то вроде


может сработать лучше. Или, конечно, просто используйте стандартный модуль Python zipfile module вместо внешней программы.