Почему сгенерированная строка содержит '\ n' - PullRequest
0 голосов
/ 08 мая 2020

Я создал это mre:

import subprocess

m = 'rsync'
url = 'mirror.nsc.liu.se/CentOS/7.8.2003/'
flags = '-avHP --delete '
destf = ''
url_prefix = 'rsync://'
root = '/tmp'
dest = 'test'

cmd = m + ' ' + flags + ' ' + url_prefix+url + ' ' +destf + ' ' + root+'/'+dest
print(cmd)
print(cmd.split(' '))
proc=subprocess.run(cmd.split(' '), capture_output=True)
print(proc.stderr)

Что дает мне следующий результат:

$ python3 test.py 
rsync -avHP --delete rsync://mirror.nsc.liu.se/CentOS/7.8.2003/  /tmp/test
['rsync', '-avHP', '--delete', '--bwlimit=800', 'rsync://mirror.nsc.liu.se/CentOS/7.8.2003/', '', '/tmp/test']
b'Unexpected local arg: \nIf arg is a remote file/dir, prefix it with a colon (:).\nrsync error: syntax or usage error (code 1) at main.c(1368) [Receiver=3.1.3]\n'

Я действительно не понимаю, что здесь не так. Насколько я знаю, в строке нет новых строк.

Если я изменю создание командной строки на это (удалите destf), проблема все равно останется:

cmd = '' + m + ' ' + flags + ' ' + url_prefix+url + ' ' + ' ' + root+'/'+dest

Но с этим (также удалите один пробел) он работает:

cmd = '' + m + ' ' + flags + ' ' + url_prefix+url + ' ' + root+'/'+dest

Если я заменю ' ' на ' ', он снова перестанет работать. Но когда я ввожу строку прямо в оболочку, она работает даже с двойными пробелами.

Так что же здесь на самом деле происходит? Я мог бы использовать свои выводы выше, чтобы быстро исправить это, но мне кажется, что это укусит меня позже. Так что же мне здесь на самом деле не хватает? Причина, по которой мне нужен параметр destf, заключается в том, что он установлен на -P, когда я использую wget, и, возможно, это может быть что-то еще для другой команды.

Ответы [ 2 ]

4 голосов
/ 08 мая 2020

Он не жалуется на новую строку в строке. Сообщение об ошибке состоит из нескольких строк, а новая строка является разделителем между строками.

Неожиданным аргументом является пустая строка '' перед '/tmp/test', потому что destf пусто.

Когда вы используете .split(' '), несколько пробелов не объединяются в один разделитель. Поэтому, когда вы выполняете

'foo  bar'.split(' ')

, результат будет

['foo', '', 'bar']

, а не

['foo', 'bar']

. Если вы хотите, чтобы несколько пробелов были объединены в один разделитель, используйте .split() вместо .split(' ')

proc=subprocess.run(cmd.split(), capture_output=True)
0 голосов
/ 08 мая 2020

Спасибо Бармару за ответ, который решил эту проблему. Во время обеда я понял, в чем проблема.

Когда программа выполняется, она просматривает переменную, традиционно называемую argv, которая, по сути, представляет собой массив строк. Оболочка обычно отвечает за преобразование строки в массив строк, поэтому, если вы вызовете эту команду:

$ foo a   b c    eee

, тогда оболочка проанализирует строку в:

argv[0] = "foo"
argv[1] = "a"
argv[2] = "b"
argv[3] = "c"
argv[4] = "eee"

Но при подходе, который я использовал, вместо этого он будет иметь следующий вид:

argv[0] = "foo"
argv[1] = "a"
argv[2] = ""
argv[3] = ""
argv[4] = "b"
argv[5] = "c"
argv[6] = ""
argv[7] = ""
argv[8] = ""
argv[9] = "eee"

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

...