229

I want to check if a string is in a text file. If it is, do X. If it's not, do Y. However, this code always returns True for some reason. Can anyone see what is wrong?

def check():
    datafile = file('example.txt')
    found = False
    for line in datafile:
        if blabla in line:
            found = True
            break

check()
if True:
    print "true"
else:
    print "false"
martineau
  • 119,623
  • 25
  • 170
  • 301
HankSmackHood
  • 4,673
  • 7
  • 29
  • 30

13 Answers13

505

The reason why you always got True has already been given, so I'll just offer another suggestion:

If your file is not too large, you can read it into a string, and just use that (easier and often faster than reading and checking line per line):

with open('example.txt') as f:
    if 'blabla' in f.read():
        print("true")

Another trick: you can alleviate the possible memory problems by using mmap.mmap() to create a "string-like" object that uses the underlying file (instead of reading the whole file in memory):

import mmap

with open('example.txt') as f:
    s = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
    if s.find('blabla') != -1:
        print('true')

NOTE: in python 3, mmaps behave like bytearray objects rather than strings, so the subsequence you look for with find() has to be a bytes object rather than a string as well, eg. s.find(b'blabla'):

#!/usr/bin/env python3
import mmap

with open('example.txt', 'rb', 0) as file, \
     mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) as s:
    if s.find(b'blabla') != -1:
        print('true')

You could also use regular expressions on mmap e.g., case-insensitive search: if re.search(br'(?i)blabla', s):

maksim
  • 806
  • 2
  • 9
  • 16
Steven
  • 28,002
  • 5
  • 61
  • 51
  • 2
    The second solution does not give the same results as `'blabla' in open('example.txt').read()` in my python 2.7 – xApple Mar 18 '13 at 11:04
  • 1
    Strange, it does work with `s.find('blabla')` (check for -1). I could swear it used to work with `in` as well... But it seems now that `in` only works for single characters... – Steven Mar 18 '13 at 11:34
  • import mmap f = open('example.txt') s = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) if 'blabla' in s: print 'true' ====> THIS DOES NOT WORK ! IT ALWAYS RETURN FALSE –  Jun 05 '14 at 15:51
  • 7
    `if 'blabla' in open('example.txt').read(): print "true"` ==> How can we close `example.txt` file in this case ? –  Jun 12 '14 at 08:11
  • 1
    @begueradj: about the mmap solution: you should use the `find()` method (see previous comments), I've updated the answer accordingly. – Steven Jun 12 '14 at 09:22
  • Yes, you are right, I posted my comment before reading yours. I tested it and it works now (about mmap) –  Jun 12 '14 at 09:24
  • @begueradj: about closing the file: it will get closed when garbage collected. If you want more explicit control (especially in other implementations than cpython), you'll have to explicitly create and close the file object (`f = open('example.txt')` and `f.close()`) or use it as a context manager (`with open('example.txt') as f:`') – Steven Jun 12 '14 at 09:24
  • 4
    `open` should generally be encapsulated in a `with` statement: `with open(file_name) as fl: return text in fl.read()` – Ohad Schneider Oct 29 '15 at 18:12
  • @Steven The solution is very useful. Is there any way to ignore the commented line starts with `#` with find? – Karthi1234 Dec 26 '17 at 16:01
  • I'm getting an error running this `TypeError: a bytes-like object is required, not 'str'`... how do I turn my object into a "bytes-like object"? – Kellen Stuart May 01 '18 at 21:53
  • 1
    Figured it out... you have to do this to the string first `some_string = str.encode(some_string)`... which converts the string to bytes – Kellen Stuart May 01 '18 at 21:58
  • Great solutions. I'd add ensuring the file exists before embedding the open() in an if statement. – BLang Aug 06 '19 at 20:33
37

As Jeffrey Said, you are not checking the value of check(). In addition, your check() function is not returning anything. Note the difference:

def check():
    with open('example.txt') as f:
        datafile = f.readlines()
    found = False  # This isn't really necessary
    for line in datafile:
        if blabla in line:
            # found = True # Not necessary
            return True
    return False  # Because you finished the search without finding

Then you can test the output of check():

if check():
    print('True')
else:
    print('False')
daaawx
  • 3,273
  • 2
  • 17
  • 16
amccormack
  • 13,207
  • 10
  • 38
  • 61
31

Here's another way to possibly answer your question using the find function which gives you a literal numerical value of where something truly is

open('file', 'r').read().find('')

in find write the word you want to find and 'file' stands for your file name

Stephan
  • 41,764
  • 65
  • 238
  • 329
amitnaruto
  • 311
  • 3
  • 2
15
if True:
    print "true"

This always happens because True is always True.

You want something like this:

if check():
    print "true"
else:
    print "false"

Good luck!

Jeffrey Greenham
  • 1,382
  • 5
  • 16
  • 33
  • I see, it works now. Seems a bit weird to me though, this means that Python says "a module is True, unless stated otherwise". So if I'd make an empty module, it'd always be true? Interesting :) – HankSmackHood Feb 09 '11 at 00:15
  • 13
    No, not at all - nothing to do with modules. You were simply checking whether True was true, which it is. – Daniel Roseman Feb 09 '11 at 00:17
6

I made a little function for this purpose. It searches for a word in the input file and then adds it to the output file.

def searcher(outf, inf, string):
    with open(outf, 'a') as f1:
        if string in open(inf).read():
            f1.write(string)
  • outf is the output file
  • inf is the input file
  • string is of course, the desired string that you wish to find and add to outf.
Coco
  • 826
  • 1
  • 12
  • 20
4

Your check function should return the found boolean and use that to determine what to print.

def check():
        datafile = file('example.txt')
        found = False
        for line in datafile:
            if blabla in line:
                found = True
                break

        return found

found = check()
if found:
    print "true"
else:
    print "false"

the second block could also be condensed to:

if check():
    print "true"
else:
    print "false"
Sam Dolan
  • 31,966
  • 10
  • 88
  • 84
  • 1
    All the above answers are dramatically FALSE except yours. I spent half a day to guess what is happening with the answer they validated while it is totally WRONG. Only yours worked for me –  Jun 05 '14 at 16:02
2

How to search the text in the file and Returns an file path in which the word is found (Как искать часть текста в файле и возвращять путь к файлу в котором это слово найдено)

import os
import re

class Searcher:
    def __init__(self, path, query):
        self.path   = path

        if self.path[-1] != '/':
            self.path += '/'

        self.path = self.path.replace('/', '\\')
        self.query  = query
        self.searched = {}

    def find(self):
        for root, dirs, files in os.walk( self.path ):
            for file in files:
                if re.match(r'.*?\.txt$', file) is not None:
                    if root[-1] != '\\':
                        root += '\\'           
                    f = open(root + file, 'rt')
                    txt = f.read()
                    f.close()

                    count = len( re.findall( self.query, txt ) )
                    if count > 0:
                        self.searched[root + file] = count

    def getResults(self):
        return self.searched

In Main()

# -*- coding: UTF-8 -*-

import sys
from search import Searcher

path = 'c:\\temp\\'
search = 'search string'


if __name__ == '__main__':

    if len(sys.argv) == 3:
        # создаем объект поисковика и передаем ему аргументы
        Search = Searcher(sys.argv[1], sys.argv[2])
    else:
        Search = Searcher(path, search)

    # начать поиск
    Search.find()

    # получаем результат
    results = Search.getResults()

    # выводим результат
    print 'Found ', len(results), ' files:'

    for file, count in results.items():
        print 'File: ', file, ' Found entries:' , count
joaquin
  • 82,968
  • 29
  • 138
  • 152
  • If you have a question about this topic that isn't answered by this Q&A, please make a new question in the top-right corner. – Sumurai8 Aug 23 '13 at 08:08
2

Two problems:

  1. Your function does not return anything; a function that does not explicitly return anything returns None (which is falsy)

  2. True is always True - you are not checking the result of your function

.

def check(fname, txt):
    with open(fname) as dataf:
        return any(txt in line for line in dataf)

if check('example.txt', 'blabla'):
    print "true"
else:
    print "false"
Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
2

If user wants to search for the word in given text file.

 fopen = open('logfile.txt',mode='r+')

  fread = fopen.readlines()

  x = input("Enter the search string: ")

  for line in fread:

      if x in line:

          print(line)
nircraft
  • 8,242
  • 5
  • 30
  • 46
Harshan Gowda
  • 181
  • 2
  • 10
1

found = False

def check():
    datafile = file('example.txt')
    for line in datafile:
        if blabla in line:
            found = True
            break
    return found

if check():
    print "true"
else:
    print "false"
karlcow
  • 6,977
  • 4
  • 38
  • 72
0
found = False
def check():
datafile = file('example.txt')
for line in datafile:
    if "blabla" in line:
        found = True
        break
return found

if check():
    print "found"
else:
    print "not found"
bruh
  • 41
  • 5
0

Here's another. Takes an absolute file path and a given string and passes it to word_find(), uses readlines() method on the given file within the enumerate() method which gives an iterable count as it traverses line by line, in the end giving you the line with the matching string, plus the given line number. Cheers.

  def word_find(file, word):
    with open(file, 'r') as target_file:
        for num, line in enumerate(target_file.readlines(), 1):
            if str(word) in line:
                print(f'<Line {num}> {line}')
            else:
                print(f'> {word} not found.')


  if __name__ == '__main__':
      file_to_process = '/path/to/file'
      string_to_find = input()
      word_find(file_to_process, string_to_find)
mana
  • 109
  • 1
  • 6
0

"found" needs to be created as global variable in the function as "if else" statement is out of the function. You also don't need to use "break" to break the loop code. The following should work to find out if the text file has desired string.

with open('text_text.txt') as f:
    datafile = f.readlines()


def check():
    global found
    found = False
    for line in datafile:
        if 'the' in line:
            found = True


check()

if found == True:
    print("True")
else:
    print("False")
Baris Ozensel
  • 433
  • 1
  • 3
  • 11