Windows上Python:作为子进程参数的路径被修改并产生错误
我在Windows上使用Python 2.6的subprocess模块,想用一个老旧的解析器应用程序(假设叫parser.py)来解析一个文本文件,代码如下:
import subprocess
k = subprocess.Popen(['python', 'parser.py', '-f C:\Report1\2011-03-14.txt'],
shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print k.communicate()
问题在于文件名是如何传递给这个老旧应用程序的,我无法修改这个应用程序的代码,只能通过Python来访问它。
运行时出现了以下错误:
IOError: [Errno 22] invalid mode (\'r\') or filename: C:\\Report1\\2011-03-14.txt
当我从错误信息中复制修改后的文件名(带有双斜杠)去检查文件是否存在时,系统却找不到这个文件。
问题:我该如何传递路径作为参数,以便它不会变成双斜杠,这样系统才能读取到文件呢?
注意:使用os.sep也无法解决这个问题。
补充说明:使用os.system执行是可以正常工作的,但问题在于如何获取输出以便后续使用。我目前在一个模块(run_parser.py)中使用os.system,然后在另一个模块(get_parse_status.py)中使用subprocess来打开run_parser.py以获取输出。如果有更好的方法,我会很感激。
谢谢你的时间。
3 个回答
"C:\Report1\2011-03-14.txt" 和 C:\Report1\2011-03-14.txt 其实是不一样的。前者实际上是一些字节串,表示为 'C:\Report1\x811-03-14.txt'。奇怪的是,这听起来并不是你的问题,但可能有关系。用 r"C:\Report1\2011-03-14.txt" 可以解决这个问题。
不过要注意,打印出来的双反斜杠并不一定意味着真的有两个反斜杠。'\' 在 Python 中是一个长度为 1 的字符串。
你试过以下方法吗:
from subprocess import Popen, PIPE
k = Popen(r'python parser.py -f "C:\Report1\2011-03-14.txt"',
shell=True,
stdout=PIPE,
stderr=STDOUT)
print k.communicate()
我发现,当通过 Popen 在命令行中传递参数时,把参数用双引号括起来是唯一可靠的方式,让它正常工作。我也不总是信任用列表调用 Popen 的方法,通常会自己构造命令。注意还有原始字符串的标识 (r'')。
路径 "C:\Report1\2011-03-14.txt"
和 C:\Report1\2011-03-14.txt
其实是不同的。前者实际上是一些字节串,像这样 'C:\\Report1\x811-03-14.txt'
。奇怪的是,这听起来并不是你遇到的问题,但可能有关系。使用 r"C:\Report1\2011-03-14.txt"
可以解决这个问题。
不过要注意,打印出来的双反斜杠并不一定意味着真的有两个反斜杠。像 '\\'
这样的字符串在 Python 中的长度是 1。
把你的参数列表改成把路径当作原始字符串来处理:
k = subprocess.Popen(['python', 'parser.py', '-f', r'C:\Report1\2011-03-14.txt'],
shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
这是一个简单的程序,它会读取一个文件并报告文件的长度:
import sys
import os
userinput = sys.argv[1]
data = open(userinput, 'rb').read()
datalength = len(data)
fname = os.path.basename(userinput)
print "%s datasize = %s" % (fname, datalength)
然后通过解释器来调用它:
>>> k = subprocess.Popen(['python', 'test2.py', 'w:\bin\test2.py'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
>>> k.communicate()
5: ('Traceback (most recent call last):\r\n File "w:\\bin\\test2.py", line 4, in <module>
data = open(userinput, \'rb\').read()
IOError: [Errno 22] invalid mode (\'rb\') or filename: 'w:\\x08in\\test2.py', None)
>>> k = subprocess.Popen(['python', r'w:\bin\test2.py', r'w:\bin\test2.py'], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
>>> k.communicate()
6: ('test2.py datasize = 194\n', None)