简体   繁体   English

for循环中的简洁性,无需列表理解

[英]concision in a for loop without list comprehension

Please don't laugh. 请别笑 I'm trying to write a simple script that will replace the hostname and IP of a base VM. 我正在尝试编写一个简单的脚本来替换基本VM的主机名和IP。 I have a working version of this, but I'm trying to make it more readable and concise. 我对此有一个工作版本,但我正在努力使其更具可读性和简洁性。 I'm getting a syntax error when trying the code below. 尝试以下代码时出现语法错误。 I was trying to make these list comprehensions, but since they are file types, that won't work. 我试图使这些列表的理解,但由于它们是文件类型,将无法正常工作。 Thanks in advance. 提前致谢。

try:
   old_network = open("/etc/sysconfig/network", "r+")
   new_network = open("/tmp/network", "w+")
   replacement = "HOSTNAME=" + str(sys.argv[1]) + "\n"

   shutil.copyfile('/etc/sysconfig/network', '/etc/sysconfig/network.setup_bak')
   for line in old_network: new_network.write(line) if not re.match(("HOSTNAME"), line)
   for line in old_network: new_network.write(replacement) if re.match(("HOSTNAME"), line)
   os.rename("/tmp/network","/etc/sysconfig/network")
   print 'Hostname set to', str(sys.argv[1])
except IOError, e:
    print "Error %s" % e
    pass

You are using some odd syntax here: 您在这里使用一些奇怪的语法:

for line in old_network: new_network.write(line) if not re.match(("HOSTNAME"), line)
for line in old_network: new_network.write(replacement) if re.match(("HOSTNAME"), line)

You need to reverse the if statement there, and put these on separate lines; 您需要在此处反转if语句,并将它们放在单独的行中; you have to combine the loops, which lets you simplify the if statements too: 您必须组合循环,这也可以简化if语句:

for line in old_network:
    if not re.match("HOSTNAME", line):
        new_network.write(line) 
    else:
        new_network.write(replacement)

You cannot really loop over an input file twice (your second loop wouldn't do anything as the file has already been read in full). 您实际上无法两次遍历输入文件(第二遍循环不会做任何事情,因为该文件已被完整读取)。

Next, you want to use the open file objects context managers (using with ) to make sure they are closed properly, whatever happens. 接下来,您想使用打开的文件对象上下文管理器( with )以确保它们正确关闭,无论发生什么情况。 You can drop the + from the file modes, you are not using the files in mixed mode, and the backup copy is probably best done first before opening anything for reading and writing just yet. 您可以从文件模式中删除+ ,而不是在混合模式下使用文件,最好先打开备份副本,然后再打开任何文件进行读写。

There is no need to use a regular expression here; 此处无需使用正则表达式; you are testing for the presence of a straightforward simple string, 'HOSTNAME' in line will do, or perhaps line.strip().startswith('HOSTNAME') to make sure the line starts with HOSTNAME . 您正在测试是否存在简单的简单字符串, 'HOSTNAME' in line是否可以使用'HOSTNAME' in line ,或者通过line.strip().startswith('HOSTNAME')来确保该行以HOSTNAME 开头

Use the tempfile module to create a temporary file with a name that won't conflict: 使用tempfile模块创建一个名称不会冲突的临时文件:

from tempfile import NamedTemporaryFile

shutil.copyfile('/etc/sysconfig/network', '/etc/sysconfig/network.setup_bak')

replacement = "HOSTNAME={}\n".format(sys.argv[1])
new_network = NamedTemporaryFile(mode='w', delete=False)

with open("/etc/sysconfig/network", "r") as old_network, new_network:
    for line in old_network:
        if line.lstrip().startswith('HOSTNAME'):
            line = replacement
        new_network.write(line) 

os.rename(new_network.name, "/etc/sysconfig/network")
print 'Hostname set to {}'.format(sys.argv[1])

You can simplify this even further by using the fileinput module , which lets you replace a file contents by simply printing; 您可以使用fileinput模块进一步简化此操作,该模块可以通过简单地打印来替换文件内容; it supports creating a backup file natively: 它支持本地创建备份文件:

import fileinput
import sys

replacement = "HOSTNAME={}\n".format(sys.argv[1])

for line in fileinput('/etc/sysconfig/network', inplace=True, backup='.setup_bak'):
    if line.lstrip().startswith('HOSTNAME'):
        line = replacement
    sys.stdout.write(line)

print 'Hostname set to {}'.format(sys.argv[1])

That's 6 lines of code (not counting imports) versus your 12. We can squash this down to just 4 by using a conditional expression, but I am not sure if that makes things more readable: 这是6行代码(不计算导入),而不是12行。我们可以使用条件表达式将其压缩到仅4行,但是我不确定这是否会使内容更易读:

for line in fileinput('/etc/sysconfig/network', inplace=True, backup='.setup_bak'):
    sys.stdout.write(replacement if line.lstrip().startswith('HOSTNAME') else line)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM