How to remove a line from a text file

Asked

Viewed 5,597 times

1

Hello. I am creating a program that opens, stores or deletes links. However, although I can remove the selected item from the link list I cannot delete the file line that corresponds to the selected item. I searched on SOEN and found no enlightening results and fileinput did not work either. Code:

    # -*- coding: cp1252 -*-
from __future__ import print_function
from Tkinter import *
import threading
import urllib
import webbrowser
import os
import fileinput

root = Tk()

root.focus_force()

#define o tamanho da janela:
root.minsize(700,500)
root.maxsize(700,500)

#variaveis globais:
global texto_link
global meter_links
global listbox

#variavel de continuação de funçoes:
hiperlink = True
hipertrue = True
supertrue = True

#vaiavel de atualizacao:
atualiza = True

#lista temporária de links:
lista = []

#titulo da janela
root.title("Links Úteis - FastLabPyTool")

#icone do canto:
root.wm_iconbitmap('icone.ico')

#texto auxiliar:
def texto_auxiliar():
    texto_link = Label(root, text = "Insere aqui o Link:", font = "Arial 10")
    texto_link.place(x = 30, y = 50)
texto_auxiliar()

#insere caixas de texto:
meter_links = Entry(root, width = 70, fg = "blue")
meter_links.place(x = 150, y = 50)

#Ficheiro:
filename = "linkers.txt"

#coloca a lista de links:
def lista_links(f, line, item):
    listbox = Listbox(root, width = 105, height = 20, bg = "cyan", fg = "blue")
    with open(filename, "r") as f:
        f = f.readlines()
        for line in f:
            listbox.insert(END, line)
        listbox.bind('<Button-3>', lambda event: eventos_linkers(event, line, f, listbox, line, item))  
    listbox.place(x = 20, y = 100)
lista_links(hiperlink, hipertrue, supertrue)

#conecta o link à internet:
def link_conections(listbox):
    items = listbox.curselection()
    for item in items:
        item = listbox.get(item)
        webbrowser.get("C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s").open(item)

#apaga os links seleccionados do arquivo:
def delete_links_arq(listbox, line, item):
    f = open(filename, "r")
    lines = f.readlines()
    f.close()
    f = open(filename, "w")
    for line in lines:
        if item in line:
            f.write(item.replace(line, ''))
            f.close()

    """for line in fileinput.input(filename, inplace=True):
        if ( line):
           continue
        print (line, end='')"""

#apaga os links:
def delete_links(listbox, items, f, line, item):
    items = listbox.curselection()
    for item in items:
        listbox.delete(item, item)
        items = listbox.curselection()
        item = listbox.get(item)
        delete_links_arq(listbox, line, item)       

#abre opções de linker através de eventos:
def eventos_linkers(event, items, f, listbox, line, item):
    link_options = ["Abrir Hiperligação", "Eliminar Hiperligação"]
    menu_options = Menu(root)
    menubar = Menu(root, tearoff = 0)
    menubar.add_cascade(label = link_options[0], command = lambda: link_conections(listbox))
    menubar.add_cascade(label = link_options[1], command = lambda: delete_links(listbox, items, f, line, item))
    menubar.tk_popup(event.x_root, event.y_root)

#decide se a caixa de texto contem um link:
def links_name(f, line, item):
    texto = meter_links.get()
    abrir = open(filename, "a")
    if (len(str(texto))) > 0:
        abrir.write((texto) + "\n")
        abrir.close()
        texto = 0
        lista_links(f, line, item)
links_name(hiperlink, hipertrue, supertrue)

#coloca os botoes:
def botoes(f, line, item):
    botao_submit = Button(root, text = "Guardar Link", bg = "cyan", fg = "black", command = lambda: links_name(f, line, item))
    botao_submit.place(x = 600, y = 45)
botoes(hiperlink, hipertrue, supertrue)

#Apenas se valer mesmo a pena :)
"""
#cria um proceso no CPU:
def processo():
    try:
        processar = thread.start_new_thread( print_time, ("Thread-1", 2, ) )
        processar.start()
    except:
        print "ERRO: Impossível criar processo!"
processo()
"""
#acaba o programa:
root.lift()
root.mainloop()
  • You will probably have to generate the file again, without the line you want to delete, or else, for better performance, mark the line as unusable (changing the first character for some special symbol) and reuse the line in the future, for data that fits. But every now and then I’d have to defragment this file in the second case.

  • What if I tried to replace the line I want to delete with a blank string?

  • 1

    Not-the correct opening is rewriting the file without the line you want - forget this story of trying to reuse the line.

1 answer

1


In function eventos_linkers where you have:

menubar.add_cascade(label = link_options[1], 
command = lambda: delete_links(listbox, items, f, line, item))

Remove the lambda for he is not needed in this case.

In function delete_links you have the following:

#apaga os links:
def delete_links(listbox, items, f, line, item):
    items = listbox.curselection()
    for item in items:
        listbox.delete(item, item)            # Aqui você deleta o item selecionado
        items = listbox.curselection()
        item = listbox.get(item)              # E aqui você acha que obtem o item selecionado
        delete_links_arq(listbox, line, item) # Por fim, você passa um valor errado aqui

For the function to work as desired, do the following:

#apaga os links:
def delete_links(listbox, items, f, line, item):
    items = listbox.curselection()
    for index in items:
        item = listbox.get(index)             # Obtem o item selecionado
        items = listbox.curselection()
        listbox.delete(index)                 # Deleta o item

        delete_links_arq(listbox, line, item) # Aqui você passa o valor correto

The function delete_links_arq in turn also has some misconceptions.

#apaga os links seleccionados do arquivo:
def delete_links_arq(listbox, line, item):
    f = open(filename, "r")    # Abre em modo somente leitura
    lines = f.readlines()
    f.close()
    f = open(filename, "w")    # Abre em modo de escrita
    for line in lines:
        if item in line:
            f.write(item.replace(line, '')) # Aqui você não está removendo a linha
            f.close()          # Fecha o arquivo precocemente

    """for line in fileinput.input(filename, inplace=True):
        if ( line):
           continue
        print (line, end='')"""

Using the approach with the Fileinput you can write this function like this:

#apaga os links seleccionados do arquivo:
def delete_links_arq(listbox, line, item):
    for line in fileinput.input(filename, inplace=True):
        if item in line:        # Se o link estiver nessa linha então faça
            pass                # Não faz nada, pula
        else:                   # Se não
            print(line, end='') # Escreve a linha no arquivo

The inplace=True causes the default output to be redirected to the file, allowing it to be rewritten without having to put the pointer at the beginning of the file or to get it.

With these modifications your code should work as expected.

I’ll still try to improve the answer..

  • Thanks :) Looks like it worked. I only had to keep lambda in the code since the program was deleting the selected link by clicking only the right side of the mouse without showing the options menu.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.