I/O operation on closed file in Python def

1

I know this is a repeat but I've looked through the answers and none of them make sense to why I'm getting ValueError: I/O operation on closed file in this specific python 2.7 function written here.

No error when separating this out to a stand alone sciptlet of:

import hashlib
import sys

sha256_hash = hashlib.sha256()

filename = 'result.txt'

with open(filename,"rb") as f:
# Read and update hash string value in blocks of 4K
    for byte_block in iter(lambda: f.read(4096),b""):
        sha256_hash.update(byte_block)
    print(sha256_hash.hexdigest())
f.close()

But when I put this into a defined function I get a ValueError on the print function.

def sha256hashcheck():
    with open( 'goldresult.txt' ,"rb") as f:
        # Read and update hash string value in blocks of 4K
        for byte_block in iter(lambda: f.read(4096),b""):
            sha256_hash.update(byte_block)
        print(sha256_hash.hexdigest())
    f.close()

sha256hashcheck()

All the other defined functions run the close() method before exiting the function, plus I make a test file on the side that no function calls and use that as the open in the def and I still get the ValueError exception

  File "parse-o365-ip-addrs.py", line 61, in sha256hashcheck
    print(sha256_hash.hexdigest())
ValueError: I/O operation on closed file

Any pointers or suggestions?

TY


Here is my entire script .. yes I'm new to python .. :)

# Initial code - https://gist.github.com/cdodd/7679fb9c5f2a2e4700c7a9c7a53e2a19 (cdodd)
import xmltodict
from socket import inet_ntoa
from struct import pack
import sys
import urllib
import hashlib

# Read from URL
data = urllib.urlopen('https://support.content.office.net/en-us/static/O365IPAddresses.xml').read()
doc = xmltodict.parse(data)
# Read from local file
# doc = xmltodict.parse(open('/path/to/file.xml').read())

# set your variables
subnettestVar = 'test.txt'
subnetresultVar = 'result.txt'
subnetgoldVar = 'goldresult.txt'
sha256_hash = hashlib.sha256()

#define your functions or classes

def calcDottedNetmask(mask):
    bits = 0xffffffff ^ (1 << 32 - mask) - 1
    return inet_ntoa(pack('>I', bits))

# Work to be done, if x['@name'] still shells exception (KeyError) on 'OneNote' because OneNote has no IPv4 address
# Still need to work out either .get (dict) or try - exception errorhandling for that issue 
def getsubnets():
    sys.stdout = open( subnettestVar , 'w')
    for x in doc['products']['product']:
        if x['@name'] in ['o365', 'Identity', 'Planner', 'ProPlus', 'Yammer', 'Teams', 'SPO', 'LYO', 'WAC']:
            for y in x['addresslist']:
                if y['@type'] == 'IPv4':
                    for ip in y['address']:
                        if '/' not in ip:
                            ip, dot_mask = (ip, '255.255.255.255')
                        else:
                            ip, cidr_mask = ip.split('/')
                            dot_mask = calcDottedNetmask(int(cidr_mask))
                        print 'network-object ' + ip + ' ' + dot_mask
                    print
    sys.stdout.close()

def removeblanklines():
    with open( subnettestVar ,'r+') as file, open( subnetresultVar ,"w") as outfile:
        for i in file.readlines():
            if not i.strip():
                continue
            if i:   
                outfile.write(i)
    file.close()
    outfile.close()

def sha256hashcheck():
    with open( 'goldresult.txt' ,"rb") as f:
        # Read and update hash string value in blocks of 4K
        for byte_block in iter(lambda: f.read(4096),b""):
            sha256_hash.update(byte_block)
        print(sha256_hash.hexdigest())
    f.close()

#Run your full program with all functions, classes and variables

getsubnets()
removeblanklines()
sha256hashcheck()
python
python-2.7
file-io
asked on Stack Overflow Jul 18, 2018 by Sconos • edited Jul 19, 2018 by Rob

2 Answers

0

All, thanks for the pointers, ShadowRanger hit the nail on the head - me being stupid and calling sys.stdout.close() .

Created a proper "with" "as" to open the file and properly call file open, just had to fuss with the print lines and call filename.write instead of relying on print statements which are console instead of file specific.

Please feel free to claim an Answer if you want ...

TY

answered on Stack Overflow Jul 18, 2018 by Sconos
0

Making an answer from my comment:

The error you're getting is for the print (hexdigest doesn't use a file at all), which indicates you've closed sys.stdout somehow. As you stated, your real code included sys.stdout.close(), which would make all default print calls fail with this error. Don't close sys.stdout and/or pass file=somefileobj as a keyword argument to print so it doesn't use sys.stdout.

answered on Stack Overflow Jul 19, 2018 by ShadowRanger

User contributions licensed under CC BY-SA 3.0