This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: sys.argv may be None or an empty list
Type: Stage:
Components: Documentation Versions: Python 3.10
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: docs@python, gvanrossum, jaraco, terry.reedy
Priority: normal Keywords:

Created on 2020-08-22 12:35 by jaraco, last changed 2022-04-11 14:59 by admin.

Messages (11)
msg375796 - (view) Author: Jason R. Coombs (jaraco) * (Python committer) Date: 2020-08-22 12:35
In [pypa/keyring#445](https://github.com/pypa/keyring/445) and issue839151, we learned that there are Python interpreters in which `sys.argv` is an empty list, is not a list, or is not initialized at all. Through use of `sys.argv[0]`, the documentation strongly implies that `sys.argv` is always a list of at least one element. The documentation makes no mention of these other cases. It would be nice if the documentation would describe what values (or absence thereof) are valid for `sys.argv`.
msg376073 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2020-08-29 19:52
The docs are normative as well as descriptive.  The specific doc for sys.argv is https://docs.python.org/3/library/sys.html#sys.argv.  It says that a proper Python stdlib sys module has an args attribute that is a non-empty list whose first item is a string.  (It implies, and to me should actually say, that all items are strings.)  Since it would seem that it is easy enough to make this true, I think that Python code should be able to depend on this as much as anything else in the docs.

The 2003 issue 839151 reported that warnings.warn exited with AttributeError when accessing a non-existent argv in an embedded interpreter.  I presume that the latter was embedded CPython.  AFAIK, the fix could have been to fix embedded interpreters to have sys.argv = ['']. (My preference.) Instead, the fix, for the warn access only, was to guard the access with try-except AttributeError.

The extended fix proposed here is to document that argv is at least optional and therefore imply that all access should be wrapped in try-except.

Guido, which idea comports with your idea of 'Python': sys has an argv with at least one string (the name, if any, of a 'program'); or sys has an optional argv, so that all bullet-proof code must guard access by catching at least AttributeError?
---

Notes on a couple of #839151 messages:

1. The fact that one can make argv be missing by deleting it was and is irrelevant.  Monkeypatching modules by deleting and changing attributes can create unlimited havoc and there is nothing special about sys.argv in this regard.

2. "this [patch] should also catch IndexError and TypeError in case sys.argv is an empty list or it is not even a list at all."  I consider this similarly irrelevant because both of these would, according to the doc, be bugs, whether originally present or introduced by monkeypatching.  

https://github.com/pypa/keyring/445 is 404 for me in multiple tries.
msg376077 - (view) Author: Jason R. Coombs (jaraco) * (Python committer) Date: 2020-08-29 20:54
Thanks Terry.

The correct URL is [jaraco/keyring#445](https://github.com/jaraco/keyring/issues/445).
msg376093 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2020-08-30 00:49
I just noticed that Py_Initialize "does not set sys.argv; use PySys_SetArgvEx() for that."
https://docs.python.org/3/c-api/init.html#c.Py_Initialize
https://docs.python.org/3/c-api/init.html#c.PySys_SetArgvEx
void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)

The latter treats failure to initialize sys.argv as fatal.  It suggests that embedders might want updatepath = 0.
msg376094 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2020-08-30 01:00
New link works and I read it, including the reference to #839151.
msg376106 - (view) Author: Jason R. Coombs (jaraco) * (Python committer) Date: 2020-08-30 13:08
One possible option to guarantee initialization could be for PyInitialize to always call PySys_SetArgvEx(1, [""], 0), providing a default value for embedded interpreters that fail to call it.
msg376110 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2020-08-30 15:33
I think it’s reasonable to expect sys.argv to have at least one item,
possibly empty. The proposed fix of setting it to [“”] seems right to me.
-- 
--Guido (mobile)
msg376118 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2020-08-30 18:10
I had the same idea late last night, though after 20 years, I have forgotten how to spell "['']" in C.  (Is some sort of allocation or declaration required?).

In the doc, change "It does not set sys.argv; use PySys_SetArgvEx() for that." to "It initializes sys.argv to ['']; use PySys_SetArgvEx() to modify it or change sys.path."

"This is a no-op when called for a second time (without calling Py_FinalizeEx() first)." needs to be respected.
msg376121 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2020-08-30 18:50
Something just occurred to me. What if the caller has already set
says.argv? We shouldn’t overwrite it. Or what if they only set it (later)
if not already set. Would we break their code?
-- 
--Guido (mobile)
msg376134 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2020-08-30 22:28
sys.argv cannot be set until sys exists.  As I mentioned above, subsequent calls before finalization must continue to be no-ops.

Code that depends on a bug, in this case of sys.argv not existing, is always vulnerable.  In this case, I would expect that people who want sys.argv to have a particular value would unconditionally set it.  If it were conditionally set, the program would likely exit or otherwise fail a test.  I intentionally have not suggested backporting a code change.
msg376138 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2020-08-31 00:02
Got it.

On Sun, Aug 30, 2020 at 15:28 Terry J. Reedy <report@bugs.python.org> wrote:

>
>
> Terry J. Reedy <tjreedy@udel.edu> added the comment:
>
>
>
> sys.argv cannot be set until sys exists.  As I mentioned above, subsequent
> calls before finalization must continue to be no-ops.
>
>
>
> Code that depends on a bug, in this case of sys.argv not existing, is
> always vulnerable.  In this case, I would expect that people who want
> sys.argv to have a particular value would unconditionally set it.  If it
> were conditionally set, the program would likely exit or otherwise fail a
> test.  I intentionally have not suggested backporting a code change.
>
>
>
> ----------
>
>
>
> _______________________________________
>
> Python tracker <report@bugs.python.org>
>
> <https://bugs.python.org/issue41615>
>
> _______________________________________
>
> --
--Guido (mobile)
History
Date User Action Args
2022-04-11 14:59:35adminsetgithub: 85781
2020-08-31 00:02:18gvanrossumsetmessages: + msg376138
2020-08-30 22:28:29terry.reedysetmessages: + msg376134
2020-08-30 18:50:41gvanrossumsetmessages: + msg376121
2020-08-30 18:10:28terry.reedysetmessages: + msg376118
2020-08-30 15:33:37gvanrossumsetmessages: + msg376110
2020-08-30 13:08:15jaracosetmessages: + msg376106
2020-08-30 01:00:43terry.reedysetmessages: + msg376094
2020-08-30 00:49:06terry.reedysetmessages: + msg376093
2020-08-29 20:54:35jaracosetmessages: + msg376077
2020-08-29 19:52:32terry.reedysetnosy: + terry.reedy, gvanrossum

messages: + msg376073
versions: + Python 3.10
2020-08-22 12:35:17jaracocreate