0

I realise that finding and replacing in a text file has already been asked, but I wasn't sure how to apply it to my situation.

Basically, this goes on earlier in the program:

while True:
    ingredient = input("what is the name of the ingredient? ")
    if ingredient == "finished":
        break
    quant = input("what is the quantity of the ingredient? "))
    unit = input("what  is the unit for the quantity? ")
    f = open(name+".txt", "a")
    f.write("\ningredient: "+ingredient+quant+unit)

Later on, I need to read the text file. However, I need to replace the numbers (quant) with the number times a different number that's inputted by the user. At the moment I have this, but I know it's all wrong.

file2 = open(recipe+".txt", "r")
file3 = open(recipe+".txt.tmp", "w")
for line in file2:
 file3.write(line.replace(numbers,numbers * serve))
print(file3)
os.remove(recipe+".txt.tmp")

the line.replace part is currently psuedocode as I'm not sure what to put there... Sorry if it's a noobie question, but I'm really stuck on this. Thanks for listening!

me.

  • Read the file and turn it into a easy to use data structure. Then, you can modify it and write it back. – Blender Jun 06 '13 at 18:54
  • 2
    Define "number". Which of the following are numbers? `1`, `two`, `4e18`, `3.14159`, `0x5f3759df` – Kevin Jun 06 '13 at 19:00

2 Answers2

2

When you're writing the file, do yourself a favor and put some kind of delimiter between the different entries:

f.write("\t".join(["\ningredient: ", ingredient, quant, unit]))

Then when you open the file again, you can just split the string of each line using that delimiter and operate on the third entry (which is where the number from quant will be):

lines = file2.readlines()
for line in lines[1:]: # To skip the first empty line in the file
    line = line.split("\t")
    line[2] = str(float(line[2]) * int(serve))
    file3.write("\t".join(line))

N.B. There are better ways to store python data (like pickles or CSV), but this should work with your current implementation without much modififcation.

ASGM
  • 11,051
  • 1
  • 32
  • 53
  • And you should make sure the individual entries do not contain the delimiter string without taking precautions. In this case, (e.g.) ingredient names should not contain tab characters. – kqr Jun 06 '13 at 19:10
  • It seemed very hopeful, and a good solution, but it returns 'IndexError: list index out of range' for the 'line[2] = float(line[2]) * serve' – John Smith Jun 06 '13 at 19:28
  • @JohnSmith some of your lines must not have all the necessary entries. Perhaps it's because each line begins with a newline (`\n`), meaning the first line only has one entry. I'll modify the code accordingly; let me know if it works. – ASGM Jun 06 '13 at 19:32
  • thanks for the quick response!! But I get a TypeError... it says 'TypeError: can't multiply sequence by non-int of type 'float''. Is this a problem because a different part of my code? – John Smith Jun 06 '13 at 19:39
  • @JohnSmith What does `serve` contain? Is it a float, an integer, or something else? If it's not a number then that might be causing the problem. – ASGM Jun 06 '13 at 19:40
  • serve is a number, an integer – John Smith Jun 06 '13 at 19:43
  • What happens if you run `type(serve)`? – ASGM Jun 06 '13 at 19:45
  • serve = (int,input("how many people would you like it to serve? ")) is what the code is – John Smith Jun 06 '13 at 19:47
  • is what I get – John Smith Jun 06 '13 at 19:50
  • @JohnSmith that's your problem right there: what you've done is create a [`tuple`](http://docs.python.org/2/library/stdtypes.html#sequence-types-str-unicode-list-tuple-bytearray-buffer-xrange) rather than an [`int`](http://docs.python.org/2/library/stdtypes.html#typesnumeric). Instead, try `serve = int(input("how many people would you like it to serve? "))`. And I'll adjust my answer to make sure it's an int when it's used for multiplication. – ASGM Jun 06 '13 at 19:53
  • really sorry to be bothering you so much... 'file3.write("\t".join(line)) TypeError: sequence item 2: expected str instance, float found' is the error I get... – John Smith Jun 06 '13 at 20:05
  • @JohnSmith ah - my fault, I keep forgetting about the issues with trying to print this all in a file. This is why it's usually better to store data like this in a better format like a pickle or CSV, where floats and ints can stay as numeric data rather than being converted to strings. My answer has been edited accordingly. – ASGM Jun 06 '13 at 20:07
  • Really really sorry, I know this bit is probably my fault. However, I get this error... 'io.UnsupportedOperation: not readable' – John Smith Jun 06 '13 at 20:22
  • @JohnSmith where do you get that error? Is it related to the code I added, or is it something else? – ASGM Jun 06 '13 at 20:27
  • no, it's a result of the code ' lines2 = file3.readlines() io.UnsupportedOperation: not readable'. Could you tell me what's wrong with this? Sorry again. – John Smith Jun 06 '13 at 20:29
  • That line's not part of my code or your posted code, so it's hard to really know. But in what you did post `file3` was opened for writing (`file3 = open(recipe+".txt.tmp", "w")` - note the `w` at the end), which means you might not be able to call `readlines()` on it. Just a guess. – ASGM Jun 06 '13 at 20:39
  • okay, I fixed it... Thanks so much!! But, it's not multiplying correctly, should I open a new thread for this? – John Smith Jun 06 '13 at 20:59
  • @JohnSmith glad to help. It might not be a bad idea to open a new thread if it's a different enough problem. – ASGM Jun 06 '13 at 21:01
  • Hang on, I think it's because of 'line[2] = str(float(line[2]) * int(serve))', it's trying to multiply a string by an integer... – John Smith Jun 06 '13 at 21:23
  • @JohnSmith is it? This line says `str( float(line[2]) * int(serve) )` ... meaning that a float and int are being multiplied, then the result is being made into a string. `line[2]` isn't converted into a string, the product is. – ASGM Jun 06 '13 at 21:27
  • *facepalm* sorry, it was a typo by me... damn it!! Thanks so much for your help :). – John Smith Jun 06 '13 at 21:44
0

You could try something like this :

    from tempfile import mkstemp
    from shutil import move
    from os import remove, close

    def replace(file_path, pattern, subst):
     #Create temp file
    fh, abs_path = mkstemp()
    old_file = open(file_path)
     for line in old_file:
     new_file.write(line.replace(pattern, subst))
     #close temp file
     new_file.close()
     close(fh)
     old_file.close()
     #Remove original file
     remove(file_path)
      #Move new file
     move(abs_path, file_path)

Check out this : Search and replace a line in a file in Python

Community
  • 1
  • 1
Abhijit
  • 1
  • 1