python - Python单击参数定义分隔符导致CSV错误“分隔符”必须是1个字符的字符串
问题描述
我正在尝试构建一个简单的click
命令行应用程序来读取具有一种类型分隔符的文件并用不同的分隔符写出相同的文件。我不想做诸如查找和替换之类的事情,因为在我不想触摸的列内可能有一些正确转义的分隔符。
我编写了一个简单的基于单击的 CLI 来执行此操作,但是在传递\t
创建制表符分隔文件时遇到了一些问题。
从下面的错误中可以看出,制表符分隔符没有正确传递到 pandas 函数以写出新文件。当我在 CLI 中间打印出分隔符时,一切看起来都正确,所以我不确定这里发生了什么。
import click
import pandas as pd
@click.command()
@click.argument('filename')
@click.argument('in_delimiter')
@click.argument('out_delimiter')
def cli(filename, in_delimiter, out_delimiter):
"""
Command line interface to change file delimiters
"""
# read in CSV file
df = pd.read_csv(filename, sep=in_delimiter)
print(len(df))
# write out CSV file
df.to_csv('output.csv', sep=out_delimiter, index=False)
print("transformation complete")
if __name__ == '__main__':
cli()
这就是我将输入和输出分隔符传递到 CLI 的方式:
python cli.py data.csv "," "\t"
这是生成的错误:
Traceback (most recent call last):
File "cli.py", line 24, in <module>
cli()
File "/home/curtis/Program_Files/miniconda3/envs/py36/lib/python3.6/site-packages/click/core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "/home/curtis/Program_Files/miniconda3/envs/py36/lib/python3.6/site-packages/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/home/curtis/Program_Files/miniconda3/envs/py36/lib/python3.6/site-packages/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/curtis/Program_Files/miniconda3/envs/py36/lib/python3.6/site-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "cli.py", line 19, in cli
df.to_csv('output.csv', sep=out_delimiter, index=False)
File "/home/curtis/Program_Files/miniconda3/envs/py36/lib/python3.6/site-packages/pandas/core/frame.py", line 1745, in to_csv
formatter.save()
File "/home/curtis/Program_Files/miniconda3/envs/py36/lib/python3.6/site-packages/pandas/io/formats/csvs.py", line 169, in save
self.writer = UnicodeWriter(f, **writer_kwargs)
File "/home/curtis/Program_Files/miniconda3/envs/py36/lib/python3.6/site-packages/pandas/io/common.py", line 521, in UnicodeWriter
return csv.writer(f, dialect=dialect, **kwds)
TypeError: "delimiter" must be a 1-character string
解决方案
要处理转义字符,您可以使用如下回调:
代码:
import codecs
def unescape(ctx, param, value):
return codecs.getdecoder("unicode_escape")(value)[0]
要使用回调,您可以执行以下操作:
@click.argument('escaped', callback=unescape)
这是如何运作的
这将使用编解码器处理传入的字符串unicode_escape
。
(来源)
测试代码:
import click
@click.command()
@click.argument('escaped', callback=unescape)
def cli(escaped):
click.echo('len: {}, ord: {}'.format(len(escaped), ord(escaped)))
if __name__ == "__main__":
commands = (
r'\t',
r'\n',
'\t',
',',
'--help',
)
import sys, time
time.sleep(1)
print('Click Version: {}'.format(click.__version__))
print('Python Version: {}'.format(sys.version))
for cmd in commands:
try:
time.sleep(0.1)
print('-----------')
print('> ' + cmd)
time.sleep(0.1)
cli(cmd.split())
except BaseException as exc:
if str(exc) != '0' and \
not isinstance(exc, (click.ClickException, SystemExit)):
raise
结果:
Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> \t
len: 1, ord: 9
-----------
> \n
len: 1, ord: 10
-----------
>
Usage: test.py [OPTIONS] ESCAPED
Error: Missing argument "escaped".
-----------
> ,
len: 1, ord: 44
-----------
> --help
Usage: test.py [OPTIONS] ESCAPED
Options:
--help Show this message and exit.
推荐阅读
- python - 如何在其他两个框架之间插入分隔框架
- java - 使用 JCo 从 SAP 系统中读取表
- python - 为什么 Tensorflow 无法计算重构参数的梯度?
- angular - 如何通过函数而不是观察者/承诺将 httpclient 响应作为变量返回
- django - django channels redis 通道层打开很多连接
- java - 我们可以使用 springboot 对 nodejs 应用程序进行身份验证吗?
- asp.net - 如何在 Open ID Authentication 中在主应用程序和虚拟应用程序之间共享授权?
- javascript - 在解决以下问题时面临问题
- java - java Selenium如何验证文本的值
- react-native - 如何在没有证书的情况下设置远程通知?(注册护士)