Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File object 'name' attribute inconsistent type and not obviously documented #76775

Closed
smontanaro opened this issue Jan 18, 2018 · 10 comments
Closed
Labels
3.7 (EOL) end of life 3.8 only security fixes docs Documentation in the Doc dir interpreter-core (Objects, Python, Grammar, and Parser dirs) topic-IO type-bug An unexpected behavior, bug, or error

Comments

@smontanaro
Copy link
Contributor

BPO 32594
Nosy @smontanaro, @bitdancer, @serhiy-storchaka, @matrixise
Superseder
  • bpo-18534: [doc] State clearly that open() 'file' param is "name" attr of the result
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2018-01-20.15:09:21.039>
    created_at = <Date 2018-01-18.13:51:34.339>
    labels = ['interpreter-core', 'type-bug', '3.8', 'expert-IO', '3.7', 'docs']
    title = "File object 'name' attribute inconsistent type and not obviously documented"
    updated_at = <Date 2018-01-20.15:09:21.038>
    user = 'https://github.com/smontanaro'

    bugs.python.org fields:

    activity = <Date 2018-01-20.15:09:21.038>
    actor = 'r.david.murray'
    assignee = 'docs@python'
    closed = True
    closed_date = <Date 2018-01-20.15:09:21.039>
    closer = 'r.david.murray'
    components = ['Documentation', 'Interpreter Core', 'IO']
    creation = <Date 2018-01-18.13:51:34.339>
    creator = 'skip.montanaro'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 32594
    keywords = []
    message_count = 10.0
    messages = ['310237', '310238', '310239', '310244', '310247', '310248', '310249', '310251', '310350', '310352']
    nosy_count = 5.0
    nosy_names = ['skip.montanaro', 'r.david.murray', 'docs@python', 'serhiy.storchaka', 'matrixise']
    pr_nums = []
    priority = 'normal'
    resolution = 'duplicate'
    stage = 'resolved'
    status = 'closed'
    superseder = '18534'
    type = 'behavior'
    url = 'https://bugs.python.org/issue32594'
    versions = ['Python 3.6', 'Python 3.7', 'Python 3.8']

    @smontanaro
    Copy link
    Contributor Author

    I stumbled on what I think is an inconsistency in the "name" attribute of file objects. When a file is opened with an existing file descriptor, the "name" attribute is of type int (this from a 3.6.4 session, but it also exists in 2.7):

    >>> import sys
    >>> sys.stderr.name
    '<stderr>'
    >>> f = open(sys.stderr.fileno())
    >>> f.name
    2
    >>> type(f.name)
    <class 'int'>

    I thought it odd that the standard I/O objects would be blessed with string filenames (despite not representing real filesystem paths), but that files opened by file descriptor would have that file descriptor as their name.

    I looked in the documentation for open():

    https://docs.python.org/3/library/functions.html#open

    but saw no mention of the "name" attribute at all. In fact, the first argument to open() is called "file", so it's not obvious that the "name" attribute needs to be a copy of that parameter.

    It seems to me that "name" attributes of open file objects should be of a consistent type, even if they might not represent an actual path in the filesystem. Even if this dual-type behavior is retained, it should be documented.

    @smontanaro smontanaro added 3.7 (EOL) end of life 3.8 only security fixes labels Jan 18, 2018
    @smontanaro smontanaro added docs Documentation in the Doc dir interpreter-core (Objects, Python, Grammar, and Parser dirs) topic-IO type-bug An unexpected behavior, bug, or error labels Jan 18, 2018
    @matrixise
    Copy link
    Member

    Hi Skip,

    I only tested with the last revision of 2.7

    Python 2.7.14+ (heads/2.7:b1a52b1167, Jan 18 2018, 14:53:29) 
    [GCC 7.2.1 20170915 (Red Hat 7.2.1-2)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import sys
    >>> sys.stderr.name
    '<stderr>'
    >>> f = open(sys.stderr.fileno())
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: coercing to Unicode: need string or buffer, int found

    I can't create a file with an int.

    @matrixise
    Copy link
    Member

    but I can confirm your issue with 3.6.4+

    Python 3.6.4+ (heads/3.6:f31c70b0d6, Jan 18 2018, 14:57:01) 
    [GCC 7.2.1 20170915 (Red Hat 7.2.1-2)] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import sys
    >>> sys.stderr.name
    '<stderr>'
    >>> f = open(sys.stderr.fileno())
    >>> f.name
    2
    >>>

    @bitdancer
    Copy link
    Member

    This has been discussed previously. The nature of the 'name' attribute for file objects is not really specified, so I'm not even sure what we would document. Maybe just that it is unspecified.

    @matrixise
    Copy link
    Member

    Maybe we could add in the documentation.

    """
    if we use a file descriptor as the parameter, the name of the returned file object will be the file descriptor itself.
    """

    @smontanaro
    Copy link
    Contributor Author

    Apologies for the incomplete report. In 2.7 this anomaly exists in the io.open() function. You are correct, builtin open() in 2.x doesn't support opening by file descriptor.

    @smontanaro
    Copy link
    Contributor Author

    I'm not terribly concerned with the end result, only that we wind up with a more consistent system. As I see it, there are two main problems:

    1. The type of the name attribute varies

    2. The name attribute appears to be undocumented, at least not in the obvious place.

    Of lesser importance, but still unintuitive, is that the "name" attribute doesn't refer to an actual name in the filesystem. (I realize that the "name" of sys.std{in,out,err} is also meaningless when interpreted as an actual filename, but that ship sailed long ago.)

    I realize that it might well be infeasible to modify behavior at this point. I do think it important to document the "name" attribute (item #2). After all, it doesn't appear to be obviously private.

    I live in a Linux-only world, so this workaround in my own code is likely not useful everywhere, but, when I try to convert a builtin file object to an io.TextIOWrapper object using io.open(f.fileno()), I actually do this:

    io.open("/dev/fd/{}".format(f.fileno()), ...)

    This gives me a meaningful "name" attribute in that it is a string, and that it names an actual filename. How this might work on systems without "/dev/fd", I don't know, but might be worth thinking about for a couple minutes before dismissing it out-of-hand.

    @bitdancer
    Copy link
    Member

    I believe you are correct that it is too late to modify the existing behavior. Too many programs depend on it. As far as documenting, my point is that it is *not specified* what the name attribute contains. It can contain literally anything, depending on the particular file object involved.

    Could we document what the open function actually does? That perhaps we could do, since it is likely that other python implementations will want to copy what CPython does in this case. But as you observe, this can also be *system dependent*, so it is not completely clear to me exactly how we should do that. That is, the description of what actually happens could be so complex that it might be better to just say something like "The exact type and value of the name attribute is not specified, but when the file is opened via a file system path it will almost always be that path as a string.".

    I'd be happy for a better answer, though :)

    @serhiy-storchaka
    Copy link
    Member

    Isn't this a duplicate of bpo-18534?

    @bitdancer
    Copy link
    Member

    Ah, yes. When I said "this has been discussed previously", that's the issue I was thinking of but couldn't find.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.7 (EOL) end of life 3.8 only security fixes docs Documentation in the Doc dir interpreter-core (Objects, Python, Grammar, and Parser dirs) topic-IO type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    4 participants