为什么生成的字符串中含有"\n"?

问题描述 投票:0回答:2

我已经创建了这个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

如果我替换掉 ' '' ' 它又停止工作了。但是当我直接在shell中输入字符串时,即使有双空格也能正常工作。

那么这里到底发生了什么?我可以用上面的发现来快速修复,但感觉以后会有麻烦。那么,我在这里到底漏掉了什么呢?我想要的原因是 destf 参数是,它被设置为 -P 当我使用 wget 并可能是另一个命令的其他东西。

python python-3.x subprocess rsync
2个回答
4
投票

它没有抱怨字符串中的换行。错误信息有多行,而换行是行间的分隔符。

意外的参数是空字符串 '' 之前 '/tmp/test' 因为 destf 是空的。

当你使用 .split(' ')多重空格不会被合并成一个定界符。因此,当你做

'foo  bar'.split(' ')

结果是

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

而非

['foo', 'bar']

如果你想把多个空格合并成一个定界符,请使用 .split() 而不是 .split(' ')

proc=subprocess.run(cmd.split(), capture_output=True)

0
投票

谢谢巴玛的回答,解决了这个问题。当我在外面吃午饭的时候,我意识到了问题的所在。

当一个程序被执行时,它在一个传统的变量中查看,这个变量叫做 argv 基本上是一个字符串数组。shell通常负责将一个字符串转换成一个字符串数组,所以如果你调用这个命令。

$ foo a   b c    eee

那么,shell就会把字符串解析成:

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"

所以字符串并没有什么问题。问题是绕过了shell所做的转换。但使用 .split() 而不是 .split(' ') 解决了。

© www.soinside.com 2019 - 2024. All rights reserved.