Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The correct way to annotate a "file type" in Python

In modern versions of Python one can have static type analysis using function annotations, according to PEP 484. This is made easy through the typing module.

Now I'm wondering how I would give a "type hint" towards a "filestream".

def myfunction(file: FILETYPE):
    pass

with open(fname) as file:
    myfunction(file)

What would I insert as FILETYPE?

Using print(type(file)) returns <class '_io.TextIOWrapper'> which isn't clear at all.

Isn't there a generic "file" type?

like image 956
paul23 Avatar asked Jan 19 '17 18:01

paul23


People also ask

What is Python type annotation?

Type annotations — also known as type signatures — are used to indicate the datatypes of variables and input/outputs of functions and methods. In many languages, datatypes are explicitly stated. In these languages, if you don't declare your datatype — the code will not run.

What type is file in Python?

There are two types of files in Python and each of them are explained below in detail with examples for your easy understanding. They are: Binary file. Text file.

Is type hinting Pythonic?

Python has always been a dynamically typed language, which means you don't have to specify data types for variables and function return values. PEP 484 introduced type hints — a way to make Python feel statically typed.


3 Answers

You can use typing.IO, typing.TextIO, and typing.BinaryIO to represent different types of I/O streams. To quote the documentation:

сlass typing.IO
class typing.TextIO
class typing.BinaryIO

Generic type IO[AnyStr] and its subclasses TextIO(IO[str]) and BinaryIO(IO[bytes]) represent the types of I/O streams such as returned by open().

like image 126
Eugene Yarmash Avatar answered Oct 09 '22 19:10

Eugene Yarmash


I think you want io.IOBase, "[t]he abstract base class for all I/O classes, acting on streams of bytes."

Note that this includes also in-memory streams like io.StringIO and io.BytesIO. Read the documentation on the module io for details.

like image 40
Stop harming Monica Avatar answered Oct 09 '22 20:10

Stop harming Monica


Either this:

from typing import TextIO # or IO or BinaryIO

def myfunction(file: TextIO ):
    pass

OR this

from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from typing import TextIO # or IO or BinaryIO

def myfunction(file: 'TextIO'):
    pass

The second approach would avoid to import the class during execution. Although python would still have to import TYPE_CHECKING during execution, it is a good practice to avoid importing classes for type hinting only: (1) doesn't get executed (just parsed), and (2) it could avoid cyclic imports.

like image 26
toto_tico Avatar answered Oct 09 '22 20:10

toto_tico