Подобный способ установки переменных окружения перед запуском новой программы является одним из способов передачи информации в новую программу. Например, можно написать сценарий, изменяющий переменную PYTHONPATH включением в нее пользовательских каталогов, перед запуском других сценариев. Благодаря этому запущенный сценарий получит свой путь поиска модулей в списке sys.path, потому что переменные оболочки передаются потомкам (такой запускающий сценарий будет представлен в конце главы 6).
Особенности переменных оболочки: родители, putenv и getenv
Обратите внимание на последнюю команду в предыдущем примере -после завершения программы верхнего уровня переменная USER получает свое первоначальное значение. Присвоения значений ключам os.environ передаются за пределы интерпретатора вниз по цепочке порожденных программ и никогда не передаются вверх процессам родительских программ (включая системную оболочку). Это относится и к программам на языке C, использующим библиотечный вызов putenv, то есть данная особенность не является ограничением, характерным именно для Python.
Это едва ли вызовет проблемы в сценарии Python, являющемся вершиной приложения. Но помните, что настройки оболочки, сделанные внутри программы, действуют, лишь пока выполняется эта программа и порожденные ею дочерние программы. Если вам потребуется экспортировать настройки окружения, чтобы они действовали после завершения программы на языке Python, вам необходимо будет найти платформозависимые расширения, реализующие такую возможность. Попробуйте поискать их на сайте http://www.python.org и в Интернете.
Другая тонкость: в нынешней реализации изменение значений в os.en-viron автоматически приводит к вызову функции os.putenv, которая вызывает функцию putenv в библиотеке языка C, если она доступна на вашей платформе, чтобы экспортировать измененное значение за пределы интерпретатора Python во все связанные с ним расширения на языке C. Однако, хотя изменения в os.environ приводят к вызову os.putenv, тем не менее прямой вызов функции os.putenv не оказывает влияния на содержимое os.environ. По этой причине для изменения окружения предпочтительнее использовать интерфейс os.environ.
Обратите также внимание, что настройки окружения загружаются в os.environ на этапе запуска программы, а не при каждом обращении к этому объекту. По этой причине изменения, выполненные в расширениях на языке C уже после запуска программы, могут не отражаться в os.environ. В языке Python на самом деле имеется более конкретная функция os.getenv, но она не вызывает функцию getenv из библиотеки языка C, а просто выбирает значения ключей из os.environ в большинстве платформ (во всех в версии 3.X). Для большинства приложений в этом нет ничего плохого, особенно если они содержат программный код только на языке Python. На платформах, где отсутствует функция putenv, для настройки окружения порождаемой программы можно передавать словарь os.environ инструментам запуска программ в виде параметра.
Стандартные потоки ввода-вывода
Модуль sys - это место обитания стандартных потоков ввода, вывода и вывода ошибок для программ на языке Python. Эти потоки обеспечивают еще один распространенный способ организации обмена данными между программами:
>>> import sys
>>> for f in (sys.stdin, sys.stdout, sys.stderr): print(f)
<_io.TextIOWrapper name=’<stdin>’ encoding=’cp437’>
<_io.TextIOWrapper name=’<stdout>’ encoding=’cp437’>
<_io.TextIOWrapper name=’<stderr>’ encoding=’cp437’>
Стандартные потоки - это всего лишь предварительно открытые объекты файлов Python, которые автоматически подключаются к стандартным потокам ввода-вывода программы при запуске. По умолчанию все они связаны с окном консоли, в котором был запущен интерпретатор Python (или программа на языке Python). Поскольку встроенные функции print и input являются не чем иным, как дружественными интерфейсами к стандартным потокам вывода-ввода, по своему действию они аналогичны прямому использованию stdout и stdin в sys:
>>> print('hello stdout world')
hello stdout world
>>> sys.stdout.write('hello stdout world' + '\n')
hello stdout world 19
>>> input('hello stdin world>')
hello stdin world>spam ‘spam’
>>> print('hello stdin world>'); sys.stdin.readline()[:-1]
hello stdin world> eggs
‘eggs’
Стандартные потоки в Windows