Взаимодействие Python-Swift (PythonKit): изменить кодировку Stdin по умолчанию

#python #swift #tensorflow #interop

#python #swift #тензорный поток #взаимодействие #swift-pythonkit

Вопрос:

Я импортировал пользовательский пакет Python в Swift с помощью PythonKit, внутри пакета Swift (SPM) с использованием XCode. Код Python в разных точках выполняется f = open("somefile","r") , а затем f.readline() .

При вызове из Swift из Python возникает следующая ошибка :

 
File "/Users/user/[...]/lib/python3.8/site-packages/module/unihan_variants.py", line 115, in unihan_variants_dict
    line = f.readline()

...

Python exception: 'ascii' codec can't decode byte 0xc2 in position 121: ordinal not in range(128)

  

Исследуя дальше, я вижу, что декодирование stdin по умолчанию — ascii вместо utf-8 :

 let sys = Python.import("sys")
print(sys.stdin.encoding) // asciii
print(sys.stdout.encoding) // ascii
  

Когда я перехожу к своему исходному модулю Python, я обнаруживаю, что могу избежать ошибки в PythonKit, указав f = open("somefile","r",encoding="utf-8") , но, к сожалению, я только что принял utf-8 во всех своих проектах на сегодняшний день.

Есть ли способ изменить кодировку по умолчанию для stdin и stdout из XCode или PythonKit?

Или необходимо / рекомендуется вернуться и указать utf-8 во всем моем коде Python?

(Это не работает) :

 sys.stdin.encoding = "utf-8" //Python exception: readonly attribute: file /Users/brianparker/Library/Developer/Xcode/DerivedData/Morphology-efqracfjfhxtguetmduhdszyzezb/SourcePackages/checkouts/PythonKit/PythonKit/Python.swift, line 540
  

Дополнительные примечания :

  • print(platform.python_version()) возвращает 3.8.5
  • Мой метод импорта моего пакета Python заключался в добавлении пути к site-packages в virtualenv к sys.path в Swift / PythonKit
  • print(sys.getdefaultencoding()) указывает на ‘utf-8’. Кажется странным, что это отличается от stdin / stdout

Обновить :

Мне удалось sys.stdin.encoding указать «utf-8», установив PYTHONIOENCODING переменную среды. Однако та же ошибка возникает при readline()

Ответ №1:

Кодировка по умолчанию Python TextIOWrapper open не определяется sys свойствами или переменными среды, предложенными в моем вопросе. Вместо этого по умолчанию используется locale.getpreferredencoding(False) .

Моя среда Python показывает следующее, что объясняет, почему мне обычно не нужно указывать кодировку при открытии файла :

 >>> locale.getlocale()
('en_US', 'UTF-8')
>>> locale.getpreferredencoding(do_setlocale=False)
'UTF-8'
  

Однако Python в Swift не имеет языкового стандарта по умолчанию (по крайней мере, при запуске на моем компьютере):

 let locale = Python.import("locale")
print(locale.getlocale()) // (None, None)
  

Следующий код установит желаемый язык для Python в приложении Swift, позволяя TextIOWrapper по умолчанию использовать utf-8 при открытии файлов :

 let locale = Python.import("locale")
if locale.getlocale().tuple2 == (Python.None,Python.None) {
   locale.setlocale(locale.LC_ALL, locale: PythonObject(["en_US","UTF-8"]))
}
  

Обратите внимание, что от 2019 года есть предложение Python о том, чтобы использовать кодировку по умолчанию в текстовом редакторе utf-8 без проверки locale , хотя я не уверен, будет ли она принята.