Skip to content

Commit e433a37

Browse files
authored
Fix changing locale. (dmlc#5314)
* Fix changing locale. * Don't use locale guard. As number parsing is implemented in house, we don't need locale. * Update doc.
1 parent 7e32af5 commit e433a37

File tree

3 files changed

+7
-25
lines changed

3 files changed

+7
-25
lines changed

doc/tutorials/saving_model.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,9 @@ You can load it back to the model generated by same version of XGBoost by:
203203
204204
bst.load_config(config)
205205
206-
This way users can study the internal representation more closely.
206+
This way users can study the internal representation more closely. Please note that some
207+
JSON generators make use of locale dependent floating point serialization methods, which
208+
is not supported by XGBoost.
207209

208210
************
209211
Future Plans

src/common/json.cc

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Copyright (c) by Contributors 2019
33
*/
44
#include <cctype>
5+
#include <locale>
56
#include <sstream>
67
#include <limits>
78
#include <cmath>
@@ -692,47 +693,23 @@ Json JsonReader::ParseBoolean() {
692693
return Json{JsonBoolean{result}};
693694
}
694695

695-
// This is an ad-hoc solution for writing numeric value in standard way. We need to add
696-
// a locale independent way of writing stream like `std::{from, to}_chars' from C++-17.
697-
// FIXME(trivialfis): Remove this.
698-
class GlobalCLocale {
699-
std::locale ori_;
700-
701-
public:
702-
GlobalCLocale() : ori_{std::locale()} {
703-
std::string const name {"C"};
704-
try {
705-
std::locale::global(std::locale(name.c_str()));
706-
} catch (std::runtime_error const& e) {
707-
LOG(FATAL) << "Failed to set locale: " << name;
708-
}
709-
}
710-
~GlobalCLocale() {
711-
std::locale::global(ori_);
712-
}
713-
};
714-
715696
Json Json::Load(StringView str) {
716-
GlobalCLocale guard;
717697
JsonReader reader(str);
718698
Json json{reader.Load()};
719699
return json;
720700
}
721701

722702
Json Json::Load(JsonReader* reader) {
723-
GlobalCLocale guard;
724703
Json json{reader->Load()};
725704
return json;
726705
}
727706

728707
void Json::Dump(Json json, std::ostream *stream, bool pretty) {
729-
GlobalCLocale guard;
730708
JsonWriter writer(stream, pretty);
731709
writer.Save(json);
732710
}
733711

734712
void Json::Dump(Json json, std::string* str, bool pretty) {
735-
GlobalCLocale guard;
736713
std::stringstream ss;
737714
JsonWriter writer(&ss, pretty);
738715
writer.Save(json);

tests/python/test_basic_models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import json
66
import testing as tm
77
import pytest
8+
import locale
89

910
dpath = 'demo/data/'
1011
dtrain = xgb.DMatrix(dpath + 'agaricus.txt.train')
@@ -300,6 +301,7 @@ def test_model_binary_io(self):
300301
'reg_loss_param']['scale_pos_weight']) == 0.5
301302

302303
def test_model_json_io(self):
304+
loc = locale.getpreferredencoding(False)
303305
model_path = 'test_model_json_io.json'
304306
parameters = {'tree_method': 'hist', 'booster': 'gbtree'}
305307
j_model = json_model(model_path, parameters)
@@ -313,6 +315,7 @@ def test_model_json_io(self):
313315
assert isinstance(j_model['learner'], dict)
314316

315317
os.remove(model_path)
318+
assert locale.getpreferredencoding(False) == loc
316319

317320
@pytest.mark.skipif(**tm.no_json_schema())
318321
def test_json_schema(self):

0 commit comments

Comments
 (0)