使用 pandas Python 2 vs 3 从标准输入读取 Excel
Read Excel from standard input using pandas Python 2 vs 3
我正在尝试编写一个用于在命令行上解析 Excel 的工具;它适用于 Python 和 pandas 的旧版本,但不适用于新版本。
Python 2 和 Python 3 之间的 sys.stdin
似乎有所不同,但我不知所措。
$ conda create -n py2 python=2.7 pandas=0.17.1 xlrd
$ source activate py2
(py2) $ cat data.xlsx | python -c "import pandas as pd; import sys; df = pd.read_excel(sys.stdin); print(df.head())"
x y
0 1 2
1 10 100
(py2) $ source deactivate
$ conda create -n py3 python=3.6 pandas=0.23.3 xlrd
$ source activate py3
(py3) $ cat data.xlsx | python -c "import pandas as pd; import sys; df = pd.read_excel(sys.stdin); print(df.head())"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Users/bilow/anaconda3/envs/py3/lib/python3.6/site-packages/pandas/util/_decorators.py", line 178, in wrapper
return func(*args, **kwargs)
File "/Users/bilow/anaconda3/envs/py3/lib/python3.6/site-packages/pandas/util/_decorators.py", line 178, in wrapper
return func(*args, **kwargs)
File "/Users/bilow/anaconda3/envs/py3/lib/python3.6/site-packages/pandas/io/excel.py", line 307, in read_excel
io = ExcelFile(io, engine=engine)
File "/Users/bilow/anaconda3/envs/py3/lib/python3.6/site-packages/pandas/io/excel.py", line 391, in __init__
data = io.read()
File "/Users/bilow/anaconda3/envs/py3/lib/python3.6/codecs.py", line 321, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 15-16: invalid continuation byte
(py3) $ source deactivate
正如您所指出的,Python 2 与 3 中的 sys.stdin
对象之间肯定存在差异。您可以通过以下方式验证这一点:
cat data.xlsx | python -c "import sys; print(sys.stdin)"
其中 Python 2 产量,
open file '<stdin>', mode 'r' at 0x104a7e0c0>
并在 Python 3 个产量中,
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='US-ASCII'>
我对 Python I/O 的了解还不够,无法说明为什么这是一个有意义的差异。不过,如果使用 sys.stdin
很重要,那么您需要检查 Python 版本并分别处理每种情况,如下所示:
# Note, you'll need to specify the `xlrd` engine for the buffer to work
$ cat data.xlsx | python -c "import pandas as pd, sys; data = sys.stdin if sys.version_info[0] == 2 else sys.stdin.buffer; df = pd.read_excel(data, engine='xlrd'); print(df.head())"
现在,这对我来说似乎很麻烦。或者,你为什么不跳过 stdin
可能的陷阱并传递文件名:
python -c "import pandas as pd, sys; df = pd.read_excel(sys.argv[1]); print(df.head())" data.xlsx
它简化并保证了 Python 2 和 3 的兼容性。
我正在尝试编写一个用于在命令行上解析 Excel 的工具;它适用于 Python 和 pandas 的旧版本,但不适用于新版本。
Python 2 和 Python 3 之间的 sys.stdin
似乎有所不同,但我不知所措。
$ conda create -n py2 python=2.7 pandas=0.17.1 xlrd
$ source activate py2
(py2) $ cat data.xlsx | python -c "import pandas as pd; import sys; df = pd.read_excel(sys.stdin); print(df.head())"
x y
0 1 2
1 10 100
(py2) $ source deactivate
$ conda create -n py3 python=3.6 pandas=0.23.3 xlrd
$ source activate py3
(py3) $ cat data.xlsx | python -c "import pandas as pd; import sys; df = pd.read_excel(sys.stdin); print(df.head())"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Users/bilow/anaconda3/envs/py3/lib/python3.6/site-packages/pandas/util/_decorators.py", line 178, in wrapper
return func(*args, **kwargs)
File "/Users/bilow/anaconda3/envs/py3/lib/python3.6/site-packages/pandas/util/_decorators.py", line 178, in wrapper
return func(*args, **kwargs)
File "/Users/bilow/anaconda3/envs/py3/lib/python3.6/site-packages/pandas/io/excel.py", line 307, in read_excel
io = ExcelFile(io, engine=engine)
File "/Users/bilow/anaconda3/envs/py3/lib/python3.6/site-packages/pandas/io/excel.py", line 391, in __init__
data = io.read()
File "/Users/bilow/anaconda3/envs/py3/lib/python3.6/codecs.py", line 321, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 15-16: invalid continuation byte
(py3) $ source deactivate
正如您所指出的,Python 2 与 3 中的 sys.stdin
对象之间肯定存在差异。您可以通过以下方式验证这一点:
cat data.xlsx | python -c "import sys; print(sys.stdin)"
其中 Python 2 产量,
open file '<stdin>', mode 'r' at 0x104a7e0c0>
并在 Python 3 个产量中,
<_io.TextIOWrapper name='<stdin>' mode='r' encoding='US-ASCII'>
我对 Python I/O 的了解还不够,无法说明为什么这是一个有意义的差异。不过,如果使用 sys.stdin
很重要,那么您需要检查 Python 版本并分别处理每种情况,如下所示:
# Note, you'll need to specify the `xlrd` engine for the buffer to work
$ cat data.xlsx | python -c "import pandas as pd, sys; data = sys.stdin if sys.version_info[0] == 2 else sys.stdin.buffer; df = pd.read_excel(data, engine='xlrd'); print(df.head())"
现在,这对我来说似乎很麻烦。或者,你为什么不跳过 stdin
可能的陷阱并传递文件名:
python -c "import pandas as pd, sys; df = pd.read_excel(sys.argv[1]); print(df.head())" data.xlsx
它简化并保证了 Python 2 和 3 的兼容性。