Search code examples
pythonperlfilehandle

Is there are Python equivalent of Perl's __DATA__ filehandle?


In Perl I often read data in from the filehandle __DATA__ at the end of the script:

while (<DATA>) {
    chomp;
    say;
}
__DATA__
line1
line2 

I find this quicker for testing code etc than reading in a file, as it means I can edit its contents on the fly.

From the doc:

The __DATA__ token tells the perl compiler that the perl code for compilation is finished.

Everything after the __DATA__ token is available for reading via the filehandle FOOBAR::DATA, where FOOBAR is the name of the current package when the __DATA__ token is reached.

Is there an equivalent in Python? If not, can anybody suggest the most Python-ish way of achieving a similar thing?


Solution

  • No, there is no direct equivalent in Python. Put your data in a multi-line variable:

    DATA = '''\
    line1
    line2
    '''
    

    You can then use DATA.splitlines() v2/v3 if you must have access to separate lines. You can put this at the end of your Python file provided you only use the name DATA in a function that is not called until after the whole module has loaded.

    Alternatively, open the current module and read from that:

    with open(__file__.rstrip('co')) as data:
        for line in data:
            while line != '# __DATA__\n':
                continue
            # do something with the rest of the 'data' in the current source file.
    
    # ...
    
    # __DATA__
    # This is going to be read later on.
    

    However the rest of the module must still at least be valid Python syntax; the Python parser can't be told to stop parsing beyond a given point.

    Generally speaking, in Python you'd just put the data file next to your source files and read that. You can use the __file__ variable to produce a path the 'current directory' and thus to any other files in the same location:

    import os.path
    
    current_dir = os.path.dirname(os.path.abspath(__file__))
    with open(os.path.join(current_dir, 'data.txt')) as data:
        # read from data.txt