2016-05-23 14 views
15

अजगर 3.5.0 पर Django v1.10 चल रहा है:नकली नई-पंक्तियों Django प्रबंधन में जोड़ा आदेश

from django.core.management.base import BaseCommand 

class Command(BaseCommand): 
    def handle(self, *args, **options): 
     print('hello ', end='', file=self.stdout) 
     print('world', file=self.stdout) 

अपेक्षित उत्पादन:

hello world 

वास्तविक उत्पादन:

hello 

world 

कैसे कर मैं सही चरित्र को सही ढंग से पास करता हूं? मैं वर्तमान में स्पष्ट रूप से स्थापित करने के एक तरीके का उपयोग:

self.stdout.ending = '' 

लेकिन इस हैक मतलब है कि आप नहीं मिलता है सभी प्रिंट समारोह की सुविधाओं, आप self.stdout.write का उपयोग करें और बाइट्स मैन्युअल तैयार करना होगा।

+0

क्या आपका उपयोग-मामला संविधान आदि के आधार पर एक संपूर्ण पाठ स्ट्रिंग बनाने की लाइनें अधिक लंबा है। कारण मैं पूछता हूं कि अगर पूरी स्ट्रिंग अग्रिम में जानी जाती है, जैसे "हैलो वर्ल्ड" के मामले में न्यूलाइन एंडिंग कैरेक्टर पर नियंत्रण प्राप्त करने के लिए stdout.write के बिना प्रिंट का उपयोग करते समय आसानी से पूर्ण लाइन के रूप में लिखा जा सकता था। तो यह मानते हुए कि आप समय से पहले पाठ को नहीं जानते हैं, क्या आप स्ट्रिंग एपेंड द्वारा टेक्स्ट नहीं बना सकते हैं जब तक पूरा टेक्स्ट प्रिंटिंग के लिए तैयार न हो जाए। –

+1

संबंधित: http://stackoverflow.com/questions/31926422/redirection-in-django-command-called-from-another-command-results-in-extraneous। और यदि आपको कोई समाधान नहीं मिलता है, तो मैं आपको जिस तरह से चाहूं व्यवहार करने के लिए अस्थायी रूप से 'प्रिंट' और/या' self.stdout 'पैचिंग करने के लिए एक सजावट या संदर्भ प्रबंधक लिखने की अनुशंसा करता हूं। –

+0

मुझे यह नहीं मिलता कि 'self.stdout.ending =' '' 'का उपयोग कैसे करें [आप] प्रिंट फ़ंक्शन और इसकी सभी अच्छी सुविधाओं का उपयोग करने से रोकता है "। आप अभी भी 'प्रिंट' का उपयोग कर सकते हैं, और आउटपुट आप उम्मीद करेंगे कि समस्या क्या है? – Louis

उत्तर

5

जब self.stdout.ending स्पष्ट रूप से स्थापित करने की उम्मीद के रूप में प्रिंट आदेश काम करता है।

लाइन समाप्त होने की आवश्यकता self.stdout.ending में file=self.stdout पर सेट की जानी चाहिए, क्योंकि यह django.core.management.base.OutputWrapper का उदाहरण है।

class Command(BaseCommand): 
    def handle(self, *args, **options): 
     self.stdout.ending = '' 
     print('hello ', end='', file=self.stdout) 
     print('world', file=self.stdout) 

रिटर्न

hello world 
+0

आप सही हैं .. सुनिश्चित नहीं है कि मैं इसे कैसे याद करने में कामयाब रहा! – wim

5

सबसे पहले, self.stdoutdjango.core.management.base.OutputWrapper कमांड का एक उदाहरण है। इसके write एक str उम्मीद नहीं bytes, इस प्रकार आप

self.stdout.write('hello ', ending='') 
self.stdout.write('world') 

उपयोग कर सकते हैं वास्तव में self.stdout.write बाइट्स को स्वीकार करता है, लेकिन केवल जब भी ending कोई रिक्त स्ट्रिंग है - कि क्योंकि इसके write विधि परिभाषित किया जाता है

def write(self, msg, style_func=None, ending=None): 
    ending = self.ending if ending is None else ending 
    if ending and not msg.endswith(ending): 
     msg += ending 
    style_func = style_func or self.style_func 
    self._out.write(force_str(style_func(msg))) 

यदि ending सत्य है, तो msg.endswith(ending) विफल होगा यदि msgbytes उदाहरण है और समाप्ति 012 है।

इसके अलावा, self.stdout के साथ सही ढंग से काम करता है जब मैं self.stdout.ending = '' स्पष्ट रूप से सेट करता हूं; हालांकि ऐसा करने का अर्थ यह हो सकता है कि self.stdout.write का उपयोग करने वाले अन्य कोड को न्यूलाइन डालने की उम्मीद है, असफल हो जाएगा।


आपके मामले में, मैं क्या चाहते हैं Command के लिए एक print विधि को परिभाषित करने के लिए है:

from django.core.management.base import OutputWrapper 

class PrintHelper: 
    def __init__(self, wrapped): 
     self.wrapped = wrapped 

    def write(self, s): 
     if isinstance(self.wrapped, OutputWrapper): 
      self.wrapped.write(s, ending='') 
     else: 
      self.wrapped.write(s) 

class Command(BaseCommand): 
    def print(self, *args, file=None, **kwargs): 
     if file is None: 
      file = self.stdout 
     print(*args, file=PrintHelper(file), **kwargs) 

    def handle(self, *args, **options): 
     self.print('hello ', end='') 
     self.print('world') 

आप अपनी खुद की BaseCommand उपवर्ग में इस कर सकते हैं - और आप अलग से उपयोग कर सकते हैं भी फ़ाइलें:

def handle(self, *args, **options): 
     for c in '|/-\\' * 100: 
      self.print('\rhello world: ' + c, end='', file=self.stderr) 
      time.sleep(0.1) 
     self.print('\bOK') 
11

रूप Django 1.10's Custom Management Commands दस्तावेज़ में बताया गया है:

आप प्रबंधन कमांड का प्रयोग और कंसोल आउटपुट प्रदान करना चाहते हैं कर रहे हैं, आप self.stdout को लिखना चाहिए और self.stderr, पर प्रिंट करने के बजाय stdout और stderr सीधे। इन प्रॉक्सी का उपयोग करके, यह आपके कस्टम कमांड का परीक्षण करना बहुत आसान हो जाता है। भी ध्यान रखें कि आप एक नई पंक्ति चरित्र के साथ संदेशों को समाप्त करने की जरूरत नहीं है, यह स्वतः ही जोड़ दिया जाएगा, जब तक आप समाप्त होने पैरामीटर निर्दिष्ट करें: अपने Command कक्षा में मुद्रित करने के लिए,

self.stdout.write("Unterminated line", ending='') 

इसलिए क्रम में स्पष्ट रूप से self.stdout.ending = '' सेट करते समय आप self.stdout वस्तु की संपत्ति को संशोधित कर रहे द्वारा

from django.core.management.base import BaseCommand 

class Command(BaseCommand): 
    def handle(self, *args, **options): 
     self.stdout.write("hello ", ending='') 
     self.stdout.write("world", ending='') 

# prints: hello world 

इसके अलावा,:, आप के रूप में अपने handle() समारोह परिभाषित करना चाहिए। लेकिन हो सकता है कि आप भविष्य में self.stdout.write() की कॉल में प्रतिबिंबित न हों। इसलिए फ़ंक्शन के भीतर ending पैरामीटर का उपयोग करना बेहतर होगा (जैसा उपर्युक्त नमूना कोड में दिखाया गया है)।

जैसा कि आपने का उल्लेख किया है "लेकिन इस हैक का मतलब है कि आपको प्रिंट फ़ंक्शन की सभी सुविधाएं नहीं मिलती हैं, आपको self.stdout.write का उपयोग करना होगा और बाइट मैन्युअल रूप से तैयार करना होगा।" नहीं, आपको bytes या print() की अन्य विशेषताओं के बारे में चिंता करने की ज़रूरत नहीं है, self.stdout.write()OutputWrapper वर्ग से संबंधित कार्य str प्रारूप में होने की अपेक्षा करता है। इसके अलावा मैं यह उल्लेख करना चाहूंगा कि print() और OutputWrapper.write()sys.stdout.write() के आसपास एक रैपर के रूप में कार्य करने के समान ही व्यवहार करता है।

print() और OutputWrapper.write() के बीच फर्क सिर्फ इतना है:

  • print() कई तार जुड़ने के लिए separator पैरामीटर के साथ *args के रूप में संदेश स्ट्रिंग स्वीकार करता है, जबकि
  • OutputWrapper.write() एक संदेश स्ट्रिंग स्वीकार करता

लेकिन सीपी के साथ तारों में स्पष्ट रूप से जुड़कर इस अंतर को आसानी से संभाला जा सकता है धमनी और इसे OutputWrapper.write() पर पास कर रहा है।

निष्कर्ष: आप print() द्वारा प्रदान के रूप में वहाँ कोई भी कर रहे हैं अतिरिक्त सुविधाओं के बारे में चिंता करने की ज़रूरत नहीं है, और self.stdout.write() का उपयोग कर के रूप में Custom Management Commands दस्तावेज़ से इस उत्तर के उद्धृत सामग्री में सुझाव के साथ आगे जाना चाहिए।

यदि आप रुचि रखते हैं, तो आप BaseCommand और OutputWrapper कक्षाओं के स्रोत कोड को यहां देख सकते हैं: Source code for django.core.management.base। यह आपके कुछ संदेहों को दूर करने में मदद कर सकता है। आप पाइथन 3 के print() से संबंधित PEP-3105 भी देख सकते हैं।

+2

धन्यवाद, आपके दावों की जांच करें! 'आउटपुटवापर 'का यह डिज़ाइन एक खराब निर्णय था, इससे कम से कम आश्चर्य के सिद्धांत का उल्लंघन करने के लिए' self.stdout' का कारण बनता है। आप उम्मीद करते हैं कि यह 'sys.stdout' जैसा व्यवहार करे, लेकिन ऐसा नहीं है, जिसका अर्थ है कि आप प्रिंट फ़ंक्शन के साथ' self.stdout' का उपयोग ठीक से नहीं कर सकते हैं जब तक आप आरटीएफएम नहीं करते। इसने मुझे कुछ बार परीक्षण में पकड़ा है, अब मैं अंततः कारणों को समझता हूं! इम्हो इंटरफ़ेस 'sys.stdout' से मेल खाना चाहिए था। या तो, या हमारे पास 'self.print' नामक एक रैपर होना चाहिए। – wim

+0

मुझे पहले से ही एक विचार था कि आप 'sys.stdout' के रूप में 'self.stdout' पर विचार कर रहे हैं, इसलिए मैंने आउटपुटवापर वर्ग से संबंधित" self.stdout.write() फ़ंक्शन का उल्लेख किया है, डेटा को स्ट्र प्रारूप में होने की उम्मीद है। यह उल्लेख करना चाहेंगे कि प्रिंट() और आउटपुट Wrapper.write() sys.stdout.write() के चारों ओर एक रैपर के रूप में अभिनय दोनों समान व्यवहार करता है। "* –

संबंधित मुद्दे