Project Euler Task 42 Solution
A Python solution can be much more succinct than what you wrote.


Reading the file: The file is a degenerate CSV file with double-quoted values.  You can use the csv module to split on commas and discard the double-quotes.
Opening the file: You can use the fileinput module to avoid hard-coding the filename.  The program will either open the filename given as a command-line argument, or read from stdin.
Generating triangle numbers: You used the given formula ½n(n+1), but if you want to generate the triangle numbers in sequence, you can just add 1+2+3+…, as per the definition.  Calling sorted(list(set(…))) is superfluous, since each appended number should be unique and increasing — if you initialize triangles = [0] instead of triangles = [0, 1].
Binary search: Using a binary search overcomplicates the solution.  A linear search is not necessarily that bad, if the list is short — as it will be in this case.  Furthermore, you could have just used a set, whose in operator works in O(1) time, instead of a list.  Writing less code means fewer opportunities to introduce bugs.

Personally, I wouldn't even bother pre-generating the triangular numbers.  Testing whether a number is triangular can be done using a simple arithmetic loop — the sort of thing that a CPU is very good at doing.  For small numbers, it's likely to be even faster than looking up entries in a data structure, since the CPU doesn't have to access memory to perform arithmetic.

If I had to test a large number t for triangularity in O(1) time, I'd use the formula in this form:

$$\lfloor \sqrt{2t} \rfloor \lceil \sqrt{2t} \rceil \stackrel{?}{=} 2t$$

… verifying that \$\sqrt{2t}\$ is not integer.
Scoring: Use the built-in sum() function with a generator expression.  The words appear to be all uppercase already; no need to .lower().  I would use ord() to convert letters to numbers.
Counting words that meet the criterion: Again, use the sum() function, which will treat True values as 1, effectively acting as a counter.  In my solution below, print(sum(is_triangular(score(w)) for w in words(fileinput.input()))) effectively summarizes the purpose of the entire program in one line.


With those suggestions, the solution can just consist of a few one-liner functions, and a loop.  It would be a good idea to write doctests to verify that the behavior is consistent with the examples given in the challenge.



import csv
import fileinput
from itertools import count

def is_triangular(number):
    """
    Test whether number is of the form n(n+1)/2.

    &gt;&gt;&gt; is_triangular(1)
    True
    &gt;&gt;&gt; is_triangular(55)
    True
    &gt;&gt;&gt; is_triangular(56)
    False
    """
    counter = count(1)
    while number &gt; 0:
        number -= next(counter)
    return number == 0

def score(word):
    """
    Calculate the word value by converting 'A'=1, 'B'=2, ..., 'Z'=26, and
    adding.  Characters must all be uppercase letters.

    &gt;&gt;&gt; score('SKY')
    55
    """
    return sum(ord(c) - (ord('A') - 1) for c in word)

def words(fileinput):
    return next(csv.reader(fileinput))

if __name__ == '__main__':
    print(sum(is_triangular(score(w)) for w in words(fileinput.input())))