使用sh模块,我想log进程的stdout / stderr并捕获stdout进行处理。该过程可能会花费很长时间,并且日志记录必须等到该过程完成后才能等待,以便用户实时查看输出。
以下内容可以很好地记录stdout / stderr。但是stdout与stderr混合在一起,没有方便的方法将它们彼此分开。
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<script src="//unpkg.com/office-ui-fabric-react/dist/office-ui-fabric-react.js"></script>
<div id="root"></div>
<script type="text/babel">
class SlotBookingComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
bookingDate: '',
buttonColor: 'red',
startTime: '',
endTime: '',
AvailableSlots: [],
slots: null
};
this.updateState = this.updateState.bind(this);
//this.handleSlots = this.handleSlots.bind(this);
}
onButtonPress() {
this.setState({
buttonColor: '#123eee'
});
}
parseIn(date_time) {
var d = new Date();
d.setHours(date_time.substring(11, 13));
d.setMinutes(date_time.substring(14, 16));
return d;
}
getTimeSlots(time1, time2) {
var arr = [];
while (time1 < time2) {
arr.push({
time: time1.toTimeString().substring(0, 5),
slots: {
'1': false,
'2': false,
'3': false,
'4': false
}
});
time1.setMinutes(time1.getMinutes() + 30);
}
return arr;
}
updateState() {
var startTime = '2019-05-06T10:30:00+05:30';
var endTime = '2019-05-06T22:00:00+05:30';
startTime = this.parseIn(startTime);
endTime = this.parseIn(endTime);
var intervals = this.getTimeSlots(startTime, endTime);
this.setState({
AvailableSlots: intervals
});
}
componentDidMount() {
this.updateState();
}
componentWillReceiveProps(props) {
this.setState({ slots: props.SlotsData });
console.log(this.state.slots);
}
handleClick(i, item, index) {
const selected = this.state.AvailableSlots[index].slots[i.toString()];
const slots = Object.assign({}, this.state.AvailableSlots[index].slots, {
[i.toString()]: !selected
});
this.setState({
AvailableSlots: [
...this.state.AvailableSlots.slice(0, index),
Object.assign({}, this.state.AvailableSlots[index], {
slots: slots,
time: item.time
}),
...this.state.AvailableSlots.slice(index + 1)
]
});
}
render() {
const AvailableSlots = this.state.AvailableSlots;
const handleSlots = (max_slot, item, index) => {
let slots = [];
for (let counter = 1; counter <= max_slot; counter++) {
slots.push(
<div
className="col"
onClick={() => this.handleClick(counter, item, index)}
style={{
margin: 5,
backgroundColor: item.slots[counter.toString()]
? 'green'
: '#575756',
height: '28px'
}}
/>
);
}
// console.log(slots);
return slots;
};
const RowData = AvailableSlots.map(function(item, index) {
//max_slot wold come from API
var max_slot = 4;
if (max_slot == 1) {
return (
<div className="row">
<p>{item}</p>
<div
className="col"
key={item}
style={{ backgroundColor: '#123eee', height: '28px' }}
>
col
</div>
</div>
);
} else {
return (
<div className="data">
<div className="row test">
<div className="slot">{item.time}- </div>
{handleSlots(max_slot, item, index)}
</div>
</div>
);
}
});
return (
<div className="container">
<div className="col-md-9 slot-window product-details">{RowData}</div>
</div>
);
}
}
ReactDOM.render(<SlotBookingComponent />, document.getElementById("root"));
</script>
输出如下:
import sh
import logging
logger = logging.getLogger(__name__)
command = sh.bash('-c', 'echo a; echo b >&2', _iter=True, _err_to_out=True)
for line in command:
logger.error(line)
print(command.stdout)
是否有一种方法可以做到但又不混合a
b
b'a\nb\n'
和stdout
?
答案 0 :(得分:0)
解决方案是将_out和_err设置为所需的日志记录功能(例如logging.error)。从stderr
或stdout
中读取新行后,它将立即被调用,并向用户逐步显示输出。
但是,设置_out
或_err
时,sh
不会收集输出,因此将无法进行处理。这就是_tee=True的目的:即使设置了stdout
或stderr
,它也会收集_out
和_err
。
import sh
import logging
logger = logging.getLogger(__name__)
command = sh.bash('-c', 'echo a; echo b >&2',
_tee=True,
_out=lambda x: logger.error(x.strip()),
_err=lambda x: logger.error(x.strip()))
print(command.stdout)
输出为
a
b
b'a\n'