【问题标题】:Python word from file search from command line argument来自命令行参数的文件搜索的 Python 单词
【发布时间】:2014-01-18 14:44:23
【问题描述】:

我有一个 6-7 行的文本文件 (test.txt)。其中3-4个有“例外”一词。同样在这3-4行中,其中2行还带有“abc”一词。我的任务是编写一个程序,通过其输出,我将能够分隔包含用户输入的任何单词的行(word1),但不能分隔包含(word1)和(word2)的行,例如“abc”:这也将是来自用户的输入)并将其写入新文件(test_mod.txt)。我必须从命令行参数执行此操作。所以这是我在命令提示符下的命令: “fileinput4.py test.txt test_mod.txt abc 异常” 此处包含“abc”和“exception”的行将被排除,仅包含“exception”一词的行将被包含并复制到 test_mod.txt 中。 到目前为止,我已经异常处理了以下事情: 1.如果两个单词相同,则显示错误消息。 2.如果少于5个参数显示错误消息。 3.如果第一个文件名拼写错误,则显示错误消息 4. 如果输入文件名和输出文件名相同,则显示错误消息。 如果有人输入了一些根本不在文本文件中的单词,我也想进行异常处理。但是我的代码中有一些错误,这件事没有发生。请帮助。每当我输入任何不在文件中的单词时,都不会打印任何内容,并且正在创建一个新文件,并且没有任何我想要阻止的错误消息。 这是我的代码:

import sys
import os


def main(): #main method
 try:    
  f1 = open(sys.argv[1], 'r')         #takes the first input file in command line

  user_input1 = (sys.argv[3])    #takes the word which is to be excluded.
  user_input2 = (sys.argv[4])    #takes the word which is to be included.
  if sys.argv[1] == sys.argv[2]: 

       sys.exit('\nERROR!!\nThe two file names cannot be the same.') 

  if sys.argv[3] != sys.argv[4]:  

    for line in f1:
         if user_input2 or user_input1 in line:

           f2 = open(sys.argv[2], 'a') 

           if user_input1 in line:
              if user_input2 in line:
                   pass

           elif user_input2 in line:
              f2.write(line)

        else:
          sys.exit('\nOne of the words or both of them does not exist.')      


  if sys.argv[3] == sys.argv[4]:  

         sys.exit('\nERROR!!\nThe word to be excluded and the word to be included     cannot be the same.') 



 except IOError:
       print('\nIO error or wrong file name.')  
 except IndexError:
       print('\nYou must enter 5 parameters.') 
 except SystemExit as e:                       
       sys.exit(e)


if __name__ == '__main__':
  main()

【问题讨论】:

  • user_input2 or user_input1 in line 应该是user_input2 in line or user_input1 in line
  • 您可以从学习argparse module 中受益。此外,您可以使用grep 完成此任务(如果您使用的是 linux/unix/osx)。此外,当单词不在文件中时,您应该考虑不要引发异常。为此,您需要在任何处理之前读取整个文件。您不妨在第一次读取文件时过滤这些行,然后在未找到输入时打印warning
  • 是的,这就是我添加 else 行的原因: sys.exit('\n其中一个或两个单词都不存在。') 但是代码没有进入该部分。我不知道为什么
  • 确保您的缩进和空格是适当的。此外,如果第一行不包含user_input2user_input1,您将退出程序。如果您的程序没有输入else: 子句,那么您可能实际上并没有提供满足该条件的输入!

标签: python file exception exception-handling


【解决方案1】:

详细说明我的评论:

代码if user_input2 or user_input1 in line 并不代表您认为的那样。你认为这意味着“如果user_input1line 中或user_input2line 中”。但是,这是不正确的。

我们来看一个简单的例子:

if True or False in [0, 1, 2, 3, 4]:
    this_will_always_be_executed()
else:
    so_this_will_never_be_run()

if True or False in [0, 1, 2, 3, 4] 行并不意味着“如果True[0, 1, 2, 3, 4] 中或False[0, 1, 2, 3, 4] 中”。这意味着ifTrue, or alternatively ifFalsein[0, 1, 2, 3, 4]`”。

换句话说,代码的意思是-if (True) or (False in [0, 1, 2, 3, 4])True 始终为真,因此在代码执行期间,解释器从不费心检查 False in [0, 1, 2, 3, 4] 是否存在。它只看到True,然后进入if 语句的主体。

同样的事情也发生在您的代码中。但是,它不太明显。您需要知道的是,Python 在某些情况下将各种值解释为TrueFalse,而不仅仅是布尔值TrueFalse,它们是像a == bc in d 这样的表达式计算结果为。

对于内置类型,例如列表、整数、浮点数和字符串,当需要布尔值时,每个值都会计算为 True(您可以通过调用函数 bool 一个对象来显式执行此操作),除了“空”值。所以bool(1) == bool(2) == bool("asdlkjhwar") == bool([1, 2, 3]) == Truebool(0) == bool([]) == bool("") == False。在你的代码中,user_input2 几乎总是一个非空字符串(或者至少你没有用它作为空字符串测试程序,user_input1 不在line 中。这表明了彻底测试的重要性。

要解决此问题,您可以将该行替换为if (user_input2 in line) or (user_input1 in line)(为便于阅读而添加了括号)。但更好的(恕我直言)会这样做 - if any(thing in line for thing in (user_input1, user_input2))。这一点值得知道,因为如果您进行类似的测试但变量数量较多(例如 user_input3、4、5 和 6),它会更快。

此外,正如 cmets 中所述,您应该查看 argparse 模块。这将使您想要实现的目标变得更加简单。

编辑:

试试这个:

   f1 = open(sys.argv[1], 'r')         #takes the first input file in command line

   user_input1 = (sys.argv[3])    #takes the word which is to be excluded.
   user_input2 = (sys.argv[4])    #takes the word which is to be included.
   if sys.argv[1] == sys.argv[2]: 

        sys.exit('\nERROR!!\nThe two file names cannot be the same.') 

   if sys.argv[3] != sys.argv[4]:  
      lines = f1.readlines()
      if any(any(argument not in line for argument in (user_input2, user_input1)) for line in lines):
          sys.exit('\nOne of the words or both of them does not exist.')
      for line in lines:
               f2 = open(sys.argv[2], 'a') 
               if not (user_input1 in line and user_input2 in line):
                   f2.write(line)

虽然你真的应该重写你的代码,这样你就不会为第一个文件中的每一行打开文件。

示例文件处理:

示例文件:

This is the first line of the file.
This line's short.
This is a line of much greater length than any other in the file.
This line has five words.
The next line is a lie.
The previous line was true.
This is the last line in the file.

示例代码:

>>> with open(filename) as f:
        for line in f:
            print(line)
            print("^That was a line of the file!")


This is the first line of the file.
^That was a line of the file!
This line's short.
^That was a line of the file!
This is a line of much greater length than any other in the file.
^That was a line of the file!
This line has five words.
^That was a line of the file!
The next line is a lie.
^That was a line of the file!
The previous line was true.
^That was a line of the file!
This is the last line in the file.
^That was a line of the file!

Here 是文件处理教程,here 是 argparse 教程。

【讨论】:

  • 非常感谢您的友好指导。但是当我尝试了你的两个建议时,现在代码只进入了“else”块。也就是说,即使我输入一个我知道文本文件中实际存在的单词,它也只会显示“其中一个单词或两个单词都不存在”。我不明白。您的逻辑完全有道理,但是为什么无论如何它只进入“else”块?
  • @sagarnildass 因为您的代码是if user_input in line,而不是if user_input in file。我将编辑我的答案以建议您可能想要做什么。
  • 非常感谢您的帮助。有用!但现在我想使用 argparse 模块来实现同样的目标。但问题是我找不到任何好的文件处理教程。你能帮我用 argparse 实现同样的目标吗?
  • 我想使用 argparse 实现同样的目的……但我还没有找到任何关于文件处理的教程。请写一个示例程序,以便我理解逻辑
  • @sweenyrod:argparse 或 getopt。如果你能把代码写给我,我会试着理解其中的逻辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-27
  • 2019-04-20
  • 2019-01-25
  • 2021-03-26
  • 1970-01-01
  • 2015-04-20
  • 1970-01-01
相关资源
最近更新 更多