Python пропускает цикл for

Я пишу код, чтобы найти широту и долготу, вычислить расстояние в пределах определенного радиуса точки и разделить два файла.

Первые 5 итераций программа работает нормально, но после этого внутренний цикл for не выполняется. Я прошел через код, он просто перешагнул цикл for. Кажется, это зависит от того, что я установил для переменной radius. Если radius меньше, это позволит меньше итераций внутреннего цикла for.

Я боюсь, что это может быть проблемой того, как я читаю в файле. Я считаю, что после 5-й итерации infile_2 пусто, но я не могу понять, как это исправить.

def main(): 

    global infile_1, infile_2

    ## import geocoded college dataset
    infile_2 = open("university_FIPS.csv", "r")

    ## import great_lakes_sample
    infile_1 = open("great_lakes_sample.csv", "r")
    outfile_within_bound = open("great_lakes_blood_college", "w")
    outfile_outside_bound = open("great_lakes_blood_NOcollege", "w")
    inside_buffer_count = 0
    outside_buffer_count = 0

    global lat_1_index, long_1_index, lat_2_index, long_2_index

    ## set radius to desired length (in miles)
    radius = 100



    ## when it is generalized, use this:
    ##    radius = input_buffer_radius()


    # create two subsets of blood drive data, one within
    # radius of college, one outside

    # skip header
    n_1 = 0
    for infile_1_line in infile_1:
        infile_1_line = infile_1_line.strip().replace("\"", "").split(","),
        infile_1_line = infile_1_line[0]        

        record_stored = False

        # find index of lat_2, long_2
        if( n_1 == 0 ):
            lat_2_index = infile_1_line.index( "lat" )
            long_2_index = infile_1_line.index( "long" )
            infile_1_header_list = infile_1_line

        # assign lat_2, long_2 latitude and longitude values
        lat_2 = infile_1_line[ lat_2_index ]
        long_2 = infile_1_line[ long_2_index ]

        # skip header
        if n_1 > 0:
            print( "\n\nExamining Record:", n_1 )

            try:
                lat_2 = float( lat_2 )
                long_2 = float( long_2 )
            except ValueError:
                print( "Value error, skipping record" )
                continue                        
            except TypeError:
                print("Type error, skipping record" )
                continue
            print( "Coordinates for record:", lat_2, long_2)


            # skip header
            n_2 = 0


            # WILL NOT ENTER LOOP ON THIRD ITERATION, it's dependent on radius, when radius is 100, it stops at n_1 = 6
            if ( n_1 > 0):
                print("\n\n\nbefore loop")            

            for infile_2_line in infile_2:
                infile_2_line = infile_2_line.strip().split(",")                                                        

                if ( n_2 == 0):
                    print( "in" )


                # find index of lat_1, long_1, create header list
                if( n_2 == 0 and n_1 == 1):
                    lat_1_index = infile_2_line.index("lat")
                    long_1_index = infile_2_line.index("long")
                    infile_2_header_list = infile_2_line

                    # creat headers for each outfile
                    write_to_csv( infile_1_header_list, outfile_within_bound )
                    write_to_csv( infile_1_header_list, outfile_outside_bound )


                # assign values for lat_1, long_1, after header
                if( n_2 > 0 ):
                    lat_1 = infile_2_line[ lat_1_index ]
                    long_1 = infile_2_line[ long_1_index ] 

                    try:
                        lat_1 = float( lat_1 )
                        long_1 = float( long_1 )
                        value_error = False
                    except ValueError:
                        continue
                    except TypeError:
                        continue

                    dist = haversine_distance(lat_1, long_1, lat_2, long_2)

                    if( dist <= radius ):
                        print( "\nRecord", n_1, "is",
                               dist, "miles from", lat_1, long_1)
                        write_to_csv( infile_1_line, outfile_within_bound )
                        record_stored = True
                        print( "Record stored in outfile_inside_bound." )
                        print( "Moving to next record." )
                        inside_buffer_count += 1
                        break

                n_2 += 1

            if( record_stored == False):

                print( "\nOutside buffer." )
                write_to_csv( infile_1_line, outfile_outside_bound )
                outside_buffer_count += 1
                print( "Record stored in outfile_outside_bound." )


        n_1 += 1

    print("\nRecords within buffer:", inside_buffer_count, "\nRecords outside buffer:", outside_buffer_count)
    infile_1.close()
    infile_1.close()
    outfile_within_bound.close()
    outfile_outside_bound.close()

person drezap    schedule 28.07.2015    source источник


Ответы (1)


Прямой ответ: когда вы перебираете файл в цикле стиля for x in f, python фактически отслеживает, как далеко вы заходите в файл. Таким образом, если вы выполните 10 итераций внутреннего цикла for до достижения точки останова, в следующий раз, когда вы попытаетесь пройтись по файлу с помощью infile_2, вы начнете 10 строк в файле!

Похоже, что в вашем случае к третьей итерации вы прочитали весь файл, поэтому итератор infile_2 будет просто сидеть в конце файла на всех последующих итерациях внешнего цикла for. Простое решение — выполнить infile_2.seek(0) до того, как запустится внутренний цикл for. Это изменит положение infile_2, чтобы снова просмотреть начало файла. Вау...

Это все прекрасно и денди, но я хотел бы предложить вам пару вещей:

  1. Когда вы открываете файлы, используйте with open("test.txt","r") as f, как показано в этой публикации SO . Это дает вам преимущество, заключающееся в том, что вам не нужно помнить о закрытии файла явно, поскольку он закрывается неявно в конце блока.

  2. Часто лучше прочитать файл в виде списка, выполнить вычисления, а затем записать все результаты одним махом. Это делает ваш код более организованным (а также более легким для чтения), а также позволяет избежать ошибок, подобных той, с которой вы столкнулись.

Чтобы проиллюстрировать эти стратегии, вот как я буду читать файлы в вашем примере кода:

def main(): 
    global infile_1, infile_2

    with open("great_lakes_sample.csv", "r") as infile_1:
        #List comprehension to format all of the lines correctly
        infile1_lines = [line.strip().replace("\"", "").split(",") for line in infile_1] 

    with open("university_FIPS.csv", "r") as infile_2:
        #List comprehension to format all of the lines correctly
        infile2_lines = [line.strip().split(",") for line in infile_2]

    #Both files are automatically closed when their respected with blocks end.
person Michael S Priz    schedule 29.07.2015