Python - läsa innehållet från filer [LÖST]

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Sep 2012

Python - läsa innehållet från filer [LÖST]

Hej!

Jag behöver hjälp angående att söka efter ett specifikt ord i en fil, hittas ordet så ska hela raden där ordet finns skrivas ut i kommandotolken. Problemet är att jag endast får detta att funka på den första raden i min fil, jag får inte till detta med raderna som kommer därefter. Någon som vet hur man löser detta?

Koden ser ut så här:

variabel = ordet jag har matat in with open("filen") as f: for line in f: if variabel in line: print line

Intel 2500k @ 4.2Ghz | Noctua NH-U14S | ASUS P8Z68-V LX | Fractal Design Define R4 | Corsair XMS3 Vengeance 2x4GB DDR3 1600 Mhz | Gigabyte GTX 970 4GB | Fractal Design Newton R2 650W | Samsung 840 EVO 250GB | Seagate SSHD 1TB | Seagate Barracuda 1 TB | Windows 10

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2009
Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Okt 2006

Fixade code-taggar, indentering är väldigt viktigt i python.

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Dec 2014
Skrivet av GreatLinkan:

Hej!

Jag behöver hjälp angående att söka efter ett specifikt ord i en fil, hittas ordet så ska hela raden där ordet finns skrivas ut i kommandotolken. Problemet är att jag endast får detta att funka på den första raden i min fil, jag får inte till detta med raderna som kommer därefter. Någon som vet hur man löser detta?

Koden ser ut så här:

variabel = ordet jag har matat in with open("filen") as f: for line in f: if variabel in line: print line

Så vitt jag ser (och testat) så borde den koden fungera. Kan du ge resterande del (Det du använder för att välja ord osv) samt vad som finns i filen den ska leta igenom?

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Sep 2012

Sidan hjälpte inte mycket.

Skrivet av Shimonu:

Fixade code-taggar, indentering är väldigt viktigt i python.

Tack!

Skrivet av AfterShock:

Så vitt jag ser (och testat) så borde den koden fungera. Kan du ge resterande del (Det du använder för att välja ord osv) samt vad som finns i filen den ska leta igenom?

Här kommer fullständiga koden:

var = input("Input: ") with open("test.txt") as f: for line in f: if var in line: print var break else: print ("ERROR") break

Textfilen innehåller bara random meningar och jag har använt mig av enter, och inte shift+enter, för att göra nya rader.

Intel 2500k @ 4.2Ghz | Noctua NH-U14S | ASUS P8Z68-V LX | Fractal Design Define R4 | Corsair XMS3 Vengeance 2x4GB DDR3 1600 Mhz | Gigabyte GTX 970 4GB | Fractal Design Newton R2 650W | Samsung 840 EVO 250GB | Seagate SSHD 1TB | Seagate Barracuda 1 TB | Windows 10

Trädvy Permalänk
Forumledare
Registrerad
Okt 2002
Skrivet av GreatLinkan:

var = input("Input: ") with open("test.txt") as f: for line in f: if var in line: print var break else: print ("ERROR") break

Om du kör med Python 2 borde du skriva raw_input i stället för input på första raden. Kör du med Python 3 kan du låta input stå kvar, men då bör du skriva print(var) (med parenteser) på rad 6.

Låt säga att du använder Python 3 (rekommenderas). Försök att i huvudet (eller med papper och penna) följa logiken i programmet för några exempelfall: exempelvis

  1. en fil där första raden matchar

  2. en fil där tredje raden matchar

  3. en fil där ingen rad matchar

Om du inte ser problemet så kan du alltid strössla lite loggningsutskrifter i programmet, likt:

var = input("Input: ") print("Öppnar filen 'test.txt'") with open("test.txt") as f: print("Loopar över varje rad...") for line in f: print(" Raden innehåller: %s" % line) print(" Innehåller raden strängen '%s'?" % var) if var in line: print(" Ja, raden matchade!") print(" Avbryter loopen i förtid") break else: print(" Nej, raden matchade inte.") print(" Avbryter loopen i förtid") break print("Loopen är klar.") print("Filen är nu stängd")

och testa att köra igenom de tidigare nämnda fallen för att se om det stämde med hur du tänkte dig att programmet skulle fungera.

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Sep 2012
Skrivet av phz:

Om du kör med Python 2 borde du skriva raw_input i stället för input på första raden. Kör du med Python 3 kan du låta input stå kvar, men då bör du skriva print(var) (med parenteser) på rad 6.

Låt säga att du använder Python 3 (rekommenderas). Försök att i huvudet (eller med papper och penna) följa logiken i programmet för några exempelfall: exempelvis

  1. en fil där första raden matchar

  2. en fil där tredje raden matchar

  3. en fil där ingen rad matchar

Om du inte ser problemet så kan du alltid strössla lite loggningsutskrifter i programmet, likt:

var = input("Input: ") print("Öppnar filen 'test.txt'") with open("test.txt") as f: print("Loopar över varje rad...") for line in f: print(" Raden innehåller: %s" % line) print(" Innehåller raden strängen '%s'?" % var) if var in line: print(" Ja, raden matchade!") print(" Avbryter loopen i förtid") break else: print(" Nej, raden matchade inte.") print(" Avbryter loopen i förtid") break print("Loopen är klar.") print("Filen är nu stängd")

och testa att köra igenom de tidigare nämnda fallen för att se om det stämde med hur du tänkte dig att programmet skulle fungera.

Tyvärr, jag ser inte logiken.

Intel 2500k @ 4.2Ghz | Noctua NH-U14S | ASUS P8Z68-V LX | Fractal Design Define R4 | Corsair XMS3 Vengeance 2x4GB DDR3 1600 Mhz | Gigabyte GTX 970 4GB | Fractal Design Newton R2 650W | Samsung 840 EVO 250GB | Seagate SSHD 1TB | Seagate Barracuda 1 TB | Windows 10

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Apr 2013

I många programmerings sammanhang använder man sig av så kallade "pipes" för att ändra "standard input" och "standard output" till och från ett program/process. Genom att göra detta kan man på ett smidigt sätt "läsa" en fil rad för rad, genom att ändra programmets standard input till filen som du vill läsa.

Ett användbart verktyg som är både lätt att använda men också leder till att man kan skriva flexiblare kod.

Notera: själva pipen, är inte "direkt" bunden till något språk, utan den ändrar endast processens "standard input/output".

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Sep 2012
Skrivet av Overwatch:

I många programmerings sammanhang använder man sig av så kallade "pipes" för att ändra "standard input" och "standard output" till och från ett program/process. Genom att göra detta kan man på ett smidigt sätt "läsa" en fil rad för rad, genom att ändra programmets standard input till filen som du vill läsa.

Ett användbart verktyg som är både lätt att använda men också leder till att man kan skriva flexiblare kod.

Notera: själva pipen, är inte "direkt" bunden till något språk, utan den ändrar endast processens "standard input/output".

Ok. Kan du ge ett kodexempel på detta? Förstår inte hur jag gör detta i min kod. Är ganska ny inom programmeringens värld.

Intel 2500k @ 4.2Ghz | Noctua NH-U14S | ASUS P8Z68-V LX | Fractal Design Define R4 | Corsair XMS3 Vengeance 2x4GB DDR3 1600 Mhz | Gigabyte GTX 970 4GB | Fractal Design Newton R2 650W | Samsung 840 EVO 250GB | Seagate SSHD 1TB | Seagate Barracuda 1 TB | Windows 10

Trädvy Permalänk
Medlem
Plats
~/Karlstad
Registrerad
Dec 2005

Dina "break" bryter ju loopen. Då du både triggar break på true och false så kommer bara första raden i filen läsas.

Bara gammalt skräp...

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Sep 2012
Skrivet av bardbard:

Dina "break" bryter ju loopen. Då du både triggar break på true och false så kommer bara första raden i filen läsas.

Amen gött, tack!

Dock så har jag ett nytt problem nu, och det är att if else satsen vart broken. Mina error meddelanden dyker upp nu ifall jag skriver in något som finns i filen samt att error meddelande kommer flera gånger på rad, oavsett ifall jag skrev in något som fanns eller ej.

Utskriften blir så här när jag skriver något som inte finns i filen:

ERROR
ERROR
ERROR
ERROR

...och så här när jag skriver in något som finns i filen:

Raden som hittas

ERROR
ERROR
ERROR

Hur löser jag så att error meddelandet endast kommer när programmet inte hittar något i min fil och då endast en gång?

Så här ser fullständiga koden ut nu:

var = input("Input: ") with open("test.txt") as f: for line in f: if var in line: print var else: print ("ERROR")

Intel 2500k @ 4.2Ghz | Noctua NH-U14S | ASUS P8Z68-V LX | Fractal Design Define R4 | Corsair XMS3 Vengeance 2x4GB DDR3 1600 Mhz | Gigabyte GTX 970 4GB | Fractal Design Newton R2 650W | Samsung 840 EVO 250GB | Seagate SSHD 1TB | Seagate Barracuda 1 TB | Windows 10

Trädvy Permalänk
Medlem
Plats
~/Karlstad
Registrerad
Dec 2005

I väntan på att mitt kaffe blir färdigt så knåpade jag ihop en fungerade fil.

Python-scripten:

var = "testord" radnummer = 1 with open("test.txt") as f: for line in f: if var in line: print("Rad "+str(radnummer)+" innehåller det magiska ordet") else: print ("ERROR! Rad "+str(radnummer)+" innehåller inte ordet :(") radnummer += 1 f.close()

test.txt

denna rad har testord inte denna inte denna heller men denna har testord och denna har testord inte denna inte denna heller men denna har testord och denna har testord inte denna inte denna heller men denna har testord här är filen slut

Min output som blir:

Rad 1 innehåller det magiska ordet ERROR! Rad 2 innehåller inte ordet :( ERROR! Rad 3 innehåller inte ordet :( Rad 4 innehåller det magiska ordet Rad 5 innehåller det magiska ordet ERROR! Rad 6 innehåller inte ordet :( ERROR! Rad 7 innehåller inte ordet :( Rad 8 innehåller det magiska ordet Rad 9 innehåller det magiska ordet ERROR! Rad 10 innehåller inte ordet :( ERROR! Rad 11 innehåller inte ordet :( Rad 12 innehåller det magiska ordet ERROR! Rad 13 innehåller inte ordet :(

Kört med python3.
Kanske kan det hjälpa dig lite på traven

Edit: Såg att du hade nytt problem. Uppdaterar min post nedan:

Nytt script:

#variabel med sökordet var = "testord" #En räknare för radnummer radnummer = 1 #En variabel som håller koll på om ordet finns i hela filen hittadeJagOrdet = False with open("test.txt") as f: for line in f: if var in line: #Vi har hittat ett ord, printar vilken rad det finns på print("Rad "+str(radnummer)+" innehåller det magiska ordet") #Vi har hittat ett ord, vi sätter denna till True hittadeJagOrdet = True #Ökar på radnumreringen med 1 radnummer += 1 #Stänger filen ifall något annat vill ha access till den f.close() #Kollar om vi hittade något ord i hela filen. Om hittadeJagOrdet är False triggas denna if-sats if not hittadeJagOrdet: print("Ditt ord fanns inte i filen :(")

Output med var=testord

Rad 1 innehåller det magiska ordet Rad 4 innehåller det magiska ordet Rad 5 innehåller det magiska ordet Rad 8 innehåller det magiska ordet Rad 9 innehåller det magiska ordet Rad 12 innehåller det magiska ordet

Output med var=ordsomintefinns

Ditt ord fanns inte i filen :(

Bara gammalt skräp...

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Apr 2013

@GreatLinkan: Här kommer ett exempel, angående användandet av pipes/stdin/stdout:

script.py

import fileinput var = "this" for line in fileinput.input(): if var in line: print("Rad "+str(fileinput.lineno())+" innehåller ordet") print("Klar")

input.txt

this row contains testord does not contain the word this row contains testord

Användandet av pipes/stdin/stdout:
Ett sätt att ändra standard input (stdin) till ett program kan göras genom att köra följande kommando från kommandotolken.

script.py < input.txt

Nu har vi sagt åt kompilatorn, kör programmet "script.py" men ändra stdin (standard input) till det du läser från input.txt

Vi kan på samma sätt ändra stdout (standard output) till valfri fil på liknande sätt. T.ex.

script.py < input.txt > out.txt

Dvs: kör "script.py" med stdin "input.txt" och skriv resultatet till filen "out.txt" (den skapas automatiskt om den inte finns).

Output

Rad 1 innehåller det magiska ordet Rad 3 innehåller det magiska ordet Klar

Notera att jag aldrig har programmerat i just Python, men har kunskap inom andra programmeringsspråk.

Edit, följande kod skriver inte ut newline när den stöter på en rad som inte innehåller vad du letar efter. Såg det kravet först nu.

import fileinput var = "this" for line in fileinput.input(): if var in line: print(line.rstrip('\n')) print("Klar")

Källa: fileinput python

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Sep 2012
Skrivet av bardbard:

I väntan på att mitt kaffe blir färdigt så knåpade jag ihop en fungerade fil.

Python-scripten:

var = "testord" radnummer = 1 with open("test.txt") as f: for line in f: if var in line: print("Rad "+str(radnummer)+" innehåller det magiska ordet") else: print ("ERROR! Rad "+str(radnummer)+" innehåller inte ordet :(") radnummer += 1 f.close()

test.txt

denna rad har testord inte denna inte denna heller men denna har testord och denna har testord inte denna inte denna heller men denna har testord och denna har testord inte denna inte denna heller men denna har testord här är filen slut

Min output som blir:

Rad 1 innehåller det magiska ordet ERROR! Rad 2 innehåller inte ordet :( ERROR! Rad 3 innehåller inte ordet :( Rad 4 innehåller det magiska ordet Rad 5 innehåller det magiska ordet ERROR! Rad 6 innehåller inte ordet :( ERROR! Rad 7 innehåller inte ordet :( Rad 8 innehåller det magiska ordet Rad 9 innehåller det magiska ordet ERROR! Rad 10 innehåller inte ordet :( ERROR! Rad 11 innehåller inte ordet :( Rad 12 innehåller det magiska ordet ERROR! Rad 13 innehåller inte ordet :(

Kört med python3.
Kanske kan det hjälpa dig lite på traven

Edit: Såg att du hade nytt problem. Uppdaterar min post nedan:

Nytt script:

#variabel med sökordet var = "testord" #En räknare för radnummer radnummer = 1 #En variabel som håller koll på om ordet finns i hela filen hittadeJagOrdet = False with open("test.txt") as f: for line in f: if var in line: #Vi har hittat ett ord, printar vilken rad det finns på print("Rad "+str(radnummer)+" innehåller det magiska ordet") #Vi har hittat ett ord, vi sätter denna till True hittadeJagOrdet = True #Ökar på radnumreringen med 1 radnummer += 1 #Stänger filen ifall något annat vill ha access till den f.close() #Kollar om vi hittade något ord i hela filen. Om hittadeJagOrdet är False triggas denna if-sats if not hittadeJagOrdet: print("Ditt ord fanns inte i filen :(")

Output med var=testord

Rad 1 innehåller det magiska ordet Rad 4 innehåller det magiska ordet Rad 5 innehåller det magiska ordet Rad 8 innehåller det magiska ordet Rad 9 innehåller det magiska ordet Rad 12 innehåller det magiska ordet

Output med var=ordsomintefinns

Ditt ord fanns inte i filen :(

Gött! Nu funkar allt, tack för all hjälp alla!

Intel 2500k @ 4.2Ghz | Noctua NH-U14S | ASUS P8Z68-V LX | Fractal Design Define R4 | Corsair XMS3 Vengeance 2x4GB DDR3 1600 Mhz | Gigabyte GTX 970 4GB | Fractal Design Newton R2 650W | Samsung 840 EVO 250GB | Seagate SSHD 1TB | Seagate Barracuda 1 TB | Windows 10

Trädvy Permalänk
Forumledare
Registrerad
Okt 2002
Skrivet av bardbard:

var = "testord" radnummer = 1 with open("test.txt") as f: for line in f: if var in line: print("Rad "+str(radnummer)+" innehåller det magiska ordet") else: print ("ERROR! Rad "+str(radnummer)+" innehåller inte ordet :(") radnummer += 1 f.close()

Att formatera strängar genom att addera dem och explicit tvinga om saker till strängar med str() är inte att föredra i Python. Bättre att interpolera; antingen med strängens mer kraftfulla format-metod eller den mer C-lika %-syntaxen. Exempel:

print("Rad %d innehåller det magiska ordet" % radnummer)

Att addera strängar med + ger merarbete vad gäller att konvertera datatyper och blir generellt svårare att läsa i allt annat än triviala fall. Det finns också risk att det leder till väldigt ineffektiva operationer då strängar är implementerade som oföränderliga ("immutable") objekt i Python, och upprepad addition behöver skapa nya temporära del-strängobjekt för varje operation. Det är bättre att även för nybörjare direkt förespråka någon form av stränginterpolation.

Vill man numrera sin loop så har Python sin enumerate-funktion, som returnerar en räknare samtidigt som objektet i sekvensen man itererar. Det är sällan eller aldrig behövligt att själv administrera räknare av denna typ.

f.close() behövs inte här, då det är hela poängen med with-konstruktionen. Denna kontexthanterare ser till att stänga filen direkt när blocket är över, oavsett hur man lämnar detta. Ser man Python-kod där någon stänger filer manuellt så skulle den sannolikt kunna skrivas mer robust med en kontexthanterare, men det finns sällan eller aldrig någon mening med att kombinera båda delar.

Så, ovanstående kan skrivas (där det inte så upplysande var bytts ut mot ett mer beskrivande namn):

search_word = "testord" with open("test.txt") as f: for i, line in enumerate(f, 1): if search_word in line: print("Rad %d innehåller det magiska ordet" % i) else: print("ERROR! Rad %d innehåller inte ordet :(" % i)

där argumentet 1 till enumerate gör att räknaren börjar på 1 snarare än 0.

Skrivet av bardbard:

#variabel med sökordet var = "testord" #En räknare för radnummer radnummer = 1 #En variabel som håller koll på om ordet finns i hela filen hittadeJagOrdet = False with open("test.txt") as f: for line in f: if var in line: #Vi har hittat ett ord, printar vilken rad det finns på print("Rad "+str(radnummer)+" innehåller det magiska ordet") #Vi har hittat ett ord, vi sätter denna till True hittadeJagOrdet = True #Ökar på radnumreringen med 1 radnummer += 1 #Stänger filen ifall något annat vill ha access till den f.close() #Kollar om vi hittade något ord i hela filen. Om hittadeJagOrdet är False triggas denna if-sats if not hittadeJagOrdet: print("Ditt ord fanns inte i filen :(")

for-satsen i Python har en else-klausul som triggar ifall man inte avbrutit loopen i förtid med en break (det brukar nämnas att just nobreak hade varit ett mer förståeligt namn än else här, men nu är det som det är). Här kan man då slippa en temporär variabel, exempelvis genom (med hänsyn tagen till tidigare notiser):

search_word = "testord" with open("test.txt") as f: for i, line in enumerate(f, 1): if search_word in line: print("Rad %d innehåller det magiska ordet" % i) break else: print("Ditt ord fanns inte i filen :(")

Allt som oftast är flaggor, manuella räknare, förinitialiserade tomma listor och liknande saker som man med fördel klarar sig helt utan i Python. Man vinner läsbarhet i form av mindre kod som mer koncist säger vad man vill göra, robusthet i form av mindre kod som kan gå fel och generellt även prestanda, även om det nästan alltid är underordnat läsbarhet i dessa sammanhang.

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.

Trädvy Permalänk
Medlem
Plats
~/Karlstad
Registrerad
Dec 2005
Skrivet av phz:

Att formatera strängar genom att addera dem och explicit tvinga om saker till strängar med str() är inte att föredra i Python. Bättre att interpolera; antingen med strängens mer kraftfulla format-metod eller den mer C-lika %-syntaxen. Exempel:

print("Rad %d innehåller det magiska ordet" % radnummer)

Att addera strängar med + ger merarbete vad gäller att konvertera datatyper och blir generellt svårare att läsa i allt annat än triviala fall. Det finns också risk att det leder till väldigt ineffektiva operationer då strängar är implementerade som oföränderliga ("immutable") objekt i Python, och upprepad addition behöver skapa nya temporära del-strängobjekt för varje operation. Det är bättre att även för nybörjare direkt förespråka någon form av stränginterpolation.

Vill man numrera sin loop så har Python sin enumerate-funktion, som returnerar en räknare samtidigt som objektet i sekvensen man itererar. Det är sällan eller aldrig behövligt att själv administrera räknare av denna typ.

f.close() behövs inte här, då det är hela poängen med with-konstruktionen. Denna kontexthanterare ser till att stänga filen direkt när blocket är över, oavsett hur man lämnar detta. Ser man Python-kod där någon stänger filer manuellt så skulle den sannolikt kunna skrivas mer robust med en kontexthanterare, men det finns sällan eller aldrig någon mening med att kombinera båda delar.

Så, ovanstående kan skrivas (där det inte så upplysande var bytts ut mot ett mer beskrivande namn):

search_word = "testord" with open("test.txt") as f: for i, line in enumerate(f, 1): if search_word in line: print("Rad %d innehåller det magiska ordet" % i) else: print("ERROR! Rad %d innehåller inte ordet :(" % i)

där argumentet 1 till enumerate gör att räknaren börjar på 1 snarare än 0.

for-satsen i Python har en else-klausul som triggar ifall man inte avbrutit loopen i förtid med en break (det brukar nämnas att just nobreak hade varit ett mer förståeligt namn än else här, men nu är det som det är). Här kan man då slippa en temporär variabel, exempelvis genom (med hänsyn tagen till tidigare notiser):

search_word = "testord" with open("test.txt") as f: for i, line in enumerate(f, 1): if search_word in line: print("Rad %d innehåller det magiska ordet" % i) break else: print("Ditt ord fanns inte i filen :(")

Allt som oftast är flaggor, manuella räknare, förinitialiserade tomma listor och liknande saker som man med fördel klarar sig helt utan i Python. Man vinner läsbarhet i form av mindre kod som mer koncist säger vad man vill göra, robusthet i form av mindre kod som kan gå fel och generellt även prestanda, även om det nästan alltid är underordnat läsbarhet i dessa sammanhang.

Snyggt och bra förklarat. Är ju själv bara hobbykodare så är långt ifrån kunnig
Hade ingen aning om att for har en else också, en mycket bra ny kunskap.
Har misstänkt länge att det finns någon inbyggd räknefunktion för att ersätta x += 1 men aldrig kommit mig för att leta.

Även på enkla exempel som detta så kan en amatör som mig lära sig nya saker.
Även om inte jag kodar saker som behöver vara särskilt effektivt så kan det ju ändå vara kul att försöka göra det så proffsigt som möjligt

Bara gammalt skräp...

Trädvy Permalänk
Medlem
Plats
Järfälla
Registrerad
Jan 2004
Skrivet av GreatLinkan:

Hej!

Jag behöver hjälp angående att söka efter ett specifikt ord i en fil, hittas ordet så ska hela raden där ordet finns skrivas ut i kommandotolken. Problemet är att jag endast får detta att funka på den första raden i min fil, jag får inte till detta med raderna som kommer därefter. Någon som vet hur man löser detta?

Koden ser ut så här:

variabel = ordet jag har matat in with open("filen") as f: for line in f: if variabel in line: print line

Vad är syftet med skriptet? Är det att lära sig python, eller ska det användas på massafiler? Kan rekommendera att kolla på grep i så fall. Mycket användbart verktyg.

Skickades från m.sweclockers.com