简体   繁体   中英

"AttributeError: 'generator' object has no attribute 'replace' "

I'm not sure why I'm seeing this error message: AttributeError: 'generator' object has no attribute 'replace' (on line: modified_file = hex_read_file.replace(batch_to_amend_final, batch_amendment_final ).

import binascii, os, re, time

os.chdir(...)
files_to_amend = os.listdir(...)
joiner = "00"

# Allow user to input the text to be replaced, and with what
while True:
    batch_to_amend3 = input("\n\nWhat number would you like to amend? \n\n >>> ")
    batch_amendment3 = input("\n\nWhat is the new number? \n\n >>> ")
    batch_to_amend2 = batch_to_amend3.encode()
    batch_to_amend = joiner.encode().join(binascii.hexlify(bytes((i,))) for i in batch_to_amend2)
    batch_amendment2 = batch_amendment3.encode()
    batch_amendment = joiner.encode().join(binascii.hexlify(bytes((i,))) for i in batch_amendment2)

# Function to translate label files
def lbl_translate(files_to_amend):
    with open(files_to_amend, 'rb') as read_file:
        read_file2 = read_file.read()
        hex_read_file = (binascii.hexlify(bytes((i,))) for i in read_file2)
        print(hex_read_file)
        modified_file = hex_read_file.replace(batch_to_amend, batch_amendment)
        with open(files_to_amend, 'wb') as write_file:
            write_file.write(modified_file)
            write_file.close()
            print("Amended: " + files_to_amend)

# Calling function to modify labels        
for label in files_to_amend:
    lbl_translate(label)

hex_read_file is a generator comprehension (note the round brackets around the statement) defined here:

hex_read_file = (binascii.hexlify(bytes((i,))) for i in read_file2)

As many already pointed out in the comments, comprehesions don't have a replace method as strings have, so you have two possibilities, depending on your specific use-case:

  1. Turn the comprehension in a bytestring and call replace on that (considering how you use write_file.write(modified_file) afterwards, this is the option that would work with that directly):
hex_read_file = bytes(binascii.hexlify(bytes((i,))) for i in read_file2)
  1. Filter and replace directly in the comprehension (and modify how you write out the result):
def lbl_translate(files_to_amend, replacement_map):
    with open(files_to_amend, 'rb') as read_file:
        read_file2 = read_file.read()
        hex_read_file = ( replacement_map.get(binascii.hexlify(bytes((i,))), binascii.hexlify(bytes((i,)))) for i in read_file2) # see Note below
        with open(files_to_amend, 'wb') as write_file:
            for b in hex_read_file:
                write_file.write(b)
        print("Amended: " + files_to_amend)

where replacement_map is a dict that you fill in with the batch_to_amend as key and the batch_amendment value (you can speficy multiple amendments too and it will work just the same). The call would then be:

for label in files_to_amend:
    lbl_translate(label,{batch_to_amend:batch_amendment})

NOTE : Using standard python dicts, becase of how comprehensions work, you need to call binascii.hexlify(bytes((i,)) twice here. A better option uses collections.defaultdict :

hex_read_file = ( replacement_map[binascii.hexlify(bytes((i,)))] for i in read_file2) # replacement_map is a collections.defaultdict

and you define replacement_map as:

from collections import defaultdict
replacement_map = defaultdict(lambda x : x) # if a value is not in the dictionary, return the key value instead.
replacement_map[batch_to_amend] = batch_amendment
for label in files_to_amend:
    lbl_translate(label, replacement_map)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM