1

The following code is from a python script I'm writing that is supposed to modify the daemons array in an Arch Linux rc.conf file. However when run, I get a ValueError saying that the operation:

for line in rc:

Cannot be performed on a closed file. I may be missing something, but as far as I can tell the file is not closed. Thanks.

rc = open('/etc/rc.conf', 'r')
tmp = open('/etc/rctmp', 'w')
for line in rc:
    if 'DAEMONS' in line and '#' not in line and 'dbus' not in line:
        line = line.split('=')[1].strip()
        line = line[1:len(line)-1]
        line = line.split()
        tmp = line[1:]
        line = [line[0]]
        line = ' '.join(line + ['dbus'] + tmp)
        line = 'DAEMONS = (' + line + ')'
tmp.write(line)
rc.close()
tmp.close()
#os.remove('/etc/rc.conf')
#shutil.move('/etc/rctmp', '/etc/rc.conf')
1
  • 1
    The indentation of tmp.write(line) is wrong and the rest is really weird. Anyways, paste the code and traceback as-is. Commented Mar 7, 2011 at 23:50

2 Answers 2

4

You reassign to tmp about 8 lines down. Then, tmp is no longer the file. At that point, its reference count may drop to zero, so Python closes it. All while you're still trying to loop over the lines in the other file.

Use a different variable name here:

...
tmp = line[1:]       # rename 'tmp' here
line = [line[0]]
line = ' '.join(line + ['dbus'] + tmp)  # and also here
...

[Edit...]

I just noticed that you are reading from rc and haven't yet written to tmp when you get the error. While you would get an error when you try tmp.write(), the variable name is probably not the reason for the issue you posted about.

Sign up to request clarification or add additional context in comments.

Comments

0

I have a slight hunch that your indentation is off. Try replacing your block of code with this.

from contextlib import nested

with nested(open('/etc/rc.conf', 'r'), open('/etc/rctmp', 'w')) as managers:
    rc_file, tmp_file = managers
    for line in rc_file:
        if 'DAEMONS' in line and '#' not in line and 'dbus' not in line:
            line = line.split('=')[1].strip()
            line = line[1:len(line) - 1]
            line = line.split()
            tmp = line[1:]
            line = [line[0]]
            line = ' '.join(line + ['dbus'] + tmp)
            line = 'DAEMONS = (' + line + ')'
        tmp_file.write(line)

EDIT: @dappawit's answer is also correct, as when a line ends up satisfying the if conditional, your code will overshadow the tmp variable by binding a string to it, and then, another error along the lines of string object doesn't have a write method will be thrown after exiting the conditional block.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.