Fix changing locale. (#5314)

* Fix changing locale.

* Don't use locale guard.

As number parsing is implemented in house, we don't need locale.

* Update doc.
This commit is contained in:
Jiaming Yuan 2020-02-17 11:31:13 +08:00 committed by fis
parent 69fc8a632f
commit 088c43d666
3 changed files with 7 additions and 25 deletions

View File

@ -195,7 +195,9 @@ You can load it back to the model generated by same version of XGBoost by:
bst.load_config(config)
This way users can study the internal representation more closely.
This way users can study the internal representation more closely. Please note that some
JSON generators make use of locale dependent floating point serialization methods, which
is not supported by XGBoost.
************
Future Plans

View File

@ -2,6 +2,7 @@
* Copyright (c) by Contributors 2019
*/
#include <cctype>
#include <locale>
#include <sstream>
#include <limits>
#include <cmath>
@ -692,47 +693,23 @@ Json JsonReader::ParseBoolean() {
return Json{JsonBoolean{result}};
}
// This is an ad-hoc solution for writing numeric value in standard way. We need to add
// a locale independent way of writing stream like `std::{from, to}_chars' from C++-17.
// FIXME(trivialfis): Remove this.
class GlobalCLocale {
std::locale ori_;
public:
GlobalCLocale() : ori_{std::locale()} {
std::string const name {"C"};
try {
std::locale::global(std::locale(name.c_str()));
} catch (std::runtime_error const& e) {
LOG(FATAL) << "Failed to set locale: " << name;
}
}
~GlobalCLocale() {
std::locale::global(ori_);
}
};
Json Json::Load(StringView str) {
GlobalCLocale guard;
JsonReader reader(str);
Json json{reader.Load()};
return json;
}
Json Json::Load(JsonReader* reader) {
GlobalCLocale guard;
Json json{reader->Load()};
return json;
}
void Json::Dump(Json json, std::ostream *stream, bool pretty) {
GlobalCLocale guard;
JsonWriter writer(stream, pretty);
writer.Save(json);
}
void Json::Dump(Json json, std::string* str, bool pretty) {
GlobalCLocale guard;
std::stringstream ss;
JsonWriter writer(&ss, pretty);
writer.Save(json);

View File

@ -5,6 +5,7 @@ import os
import json
import testing as tm
import pytest
import locale
dpath = 'demo/data/'
dtrain = xgb.DMatrix(dpath + 'agaricus.txt.train')
@ -300,6 +301,7 @@ class TestModels(unittest.TestCase):
'reg_loss_param']['scale_pos_weight']) == 0.5
def test_model_json_io(self):
loc = locale.getpreferredencoding(False)
model_path = 'test_model_json_io.json'
parameters = {'tree_method': 'hist', 'booster': 'gbtree'}
j_model = json_model(model_path, parameters)
@ -313,6 +315,7 @@ class TestModels(unittest.TestCase):
assert isinstance(j_model['learner'], dict)
os.remove(model_path)
assert locale.getpreferredencoding(False) == loc
@pytest.mark.skipif(**tm.no_json_schema())
def test_json_schema(self):