import argparse
import re
from tokenize import generate_tokens, STRING, untokenize
# Tool for the automatic (and manual) conversion of single-quoted strings to double-quoted ones
# Reference for string literals: https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
LONG_STRING_REGEX = re.compile(r"([fruFRU]*)'''(.*)'''", re.DOTALL)
SHORT_STRING_REGEX = re.compile(r"([fruFRU]*)'(.*)'") # only if LONG_STRING_REGEX doesn't match
def single_to_double_quotes(infilename, outfilename, long_too):
convs_done = 0
manual_conv_starts = []
output_tokens = []
with open(infilename) as infile:
for t in generate_tokens(infile.readline):
if t.type == STRING:
if m := LONG_STRING_REGEX.fullmatch(t.string):
if long_too:
prefix, value = m.groups()
if '"""' in value:
manual_conv_starts.append(t.start)
else:
t = (STRING, f'{prefix}"""{value}"""', t.start, t.end, t.line)
convs_done += 1
elif m := SHORT_STRING_REGEX.fullmatch(t.string):
prefix, value = m.groups()
if '"' in value or "'" in value:
manual_conv_starts.append(t.start)
else:
t = (STRING, f'{prefix}"{value}"', t.start, t.end, t.line)
convs_done += 1
output_tokens.append(t)
with open(outfilename, 'w') as outfile:
outfile.write(untokenize(output_tokens))
return convs_done, manual_conv_starts
parser = argparse.ArgumentParser(description='safely convert single quotes to double quotes')
parser.add_argument('infilename', metavar='INPUT_FILE', help='the input file')
parser.add_argument('outfilename', metavar='OUTPUT_FILE', help='the output file')
parser.add_argument('--long', '-l', action='store_true', help='also convert "long" (triple-quoted) strings')
args = parser.parse_args() # type: argparse.Namespace
infilename = args.infilename # type: str
outfilename = args.outfilename # type: str
long_too = bool(args.long)
print(f"input file: {infilename}")
print(f"long string conversion {('disabled', 'enabled')[long_too]}")
convs_done, manual_conv_starts = single_to_double_quotes(infilename, outfilename, long_too)
print(f"strings converted: {convs_done}")
print(f"possible manual conversions: {len(manual_conv_starts)}")
for start in manual_conv_starts:
print(f" {outfilename} line {start[0]} char {start[1] + 1}")
print(f"output file: {outfilename}")
字符串 输出示例(不带-l选项):
input file: single_to_double_quotes_TEST.py
long string conversion disabled
strings converted: 5
possible manual conversions: 3
single_to_double_quotes_CONV.py line 3 char 5
single_to_double_quotes_CONV.py line 4 char 5
single_to_double_quotes_CONV.py line 12 char 7
output file: single_to_double_quotes_CONV.py
型 single_to_double_quotes_TEST.py:
n = 123
s = 'abc'
t = 'd"e"f'
u = 'g\'h\'i'
l = '''
"let's see"
'''
w, x, y, z = '''xyz''', '''"""yz''', '''x"""z''', '''xy"""'''
print(f'{s=}')
d = {'a': 1, 'b': 2, 'c': 3}
print(f"{d['a']=}")
print(f'{d["a"]=}')
型 single_to_double_quotes_CONV.py:
n = 123
s = "abc"
t = 'd"e"f'
u = 'g\'h\'i'
l = '''
"let's see"
'''
w, x, y, z = '''xyz''', '''"""yz''', '''x"""z''', '''xy"""'''
print(f"{s=}")
d = {"a": 1, "b": 2, "c": 3}
print(f"{d['a']=}")
print(f'{d["a"]=}')
6条答案
按热度按时间svdrlsy41#
在
Preferences
中,在搜索栏中输入double-quoted
。这将建议Editor->Intentions
。有一个选项可以将双引号字符串转换为单引号字符串,反之亦然。检查此选项以查看是否启用。当您选择这样一个字符串的一个示例,并单击“灯泡”时,这可能会(也可能不会)为您提供通过点击向右箭头将其应用于整个文件的选项。
如果没有,它至少可以减轻你的痛苦,因为你可以简单地在每个示例上单击一次,然后使用灯泡来修复它。在
Intentions
上查找文档并不是那么富有成效,关于如何在文件中应用它们或将它们包括在代码检查中。这可能是社区版和完整版之间的区别。不过,正如@acushner的评论所暗示的那样,根据我的个人经验和偏好,单引号似乎是更常用的风格,可以说是次罗莎佳能。
(To老实说,在这一点上,它是如此根深蒂固,我发现自己的单引号散文。但我认为这是一个个人问题,和TMI。'做你自己。')
mzillmmw2#
我认为有一个更简单的解决方案没有被讨论,那就是PyCharm的查找和替换功能,它可以忽略注解和字符串字面量,这似乎可以做你想要的事情,而不需要做太多的工作,也没有什么空间来处理边缘情况:
要忽略三重单引号,你可以使用这个正则表达式,它是我从this SO post复制的:
字符串
的
kyxcudwk3#
我知道你问过如何在PyCharm中实现它,但我会提出一个工具来代替,因为在我的测试中,它可以正常工作。你仍然可以在PyCharm的终端窗口中运行它,这使得它成为你问题的有效答案;-)。
该工具(源代码如下)基于Python的tokenizer。这保证了只有单引号包围的字符串文字可以被替换。
此外,避免了不直接和安全的转换,甚至可能不需要的转换。报告可能需要手动干预的文件位置。
在
find
命令的帮助下,您可以立即将此工具应用于整个源代码树。字符串
输出示例(不带
-l
选项):型
single_to_double_quotes_TEST.py
:型
single_to_double_quotes_CONV.py
:型
在源代码树的副本上,就像在git checkout 时一样,你可以做以下事情:
型
这会将每个文件转换为自身。
如果您不熟悉argparse:请从
型
我建议您修改该工具以最适合您的需要。
2w2cym1i4#
这可以使用黑色格式来完成
通过执行
pip install black
安装黑色然后执行
black .
来执行格式化。这不仅可以处理单引号,还可以将代码格式化为可读性更强的格式。您可以为black提供很多选项来自定义black的格式设置。
您可以在这里查看这些选项:https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#command-line-options
20jt8wwn5#
我不知道它是否对任何人都有帮助,但我更喜欢双击选择一个单词,而不是选择引号之间的整个字符串,然后按Alt + Enter。或者反之亦然。你甚至不需要双击,因为Pycharm足够聪明,可以选择第一对引号。我觉得这很舒服。我我不知道它对于非常复杂的嵌套字符串是否足够聪明,但你可以尝试。如果它能让我们选择多行并修复它们,那将是很好的,但这就是黑色在这里的作用,对吗?
zd287kbt6#
Ctrl+R将弹出查找/替换对话框。只需在查找字段中输入“,在替换字段中输入“。