2010-06-15 2 views
2
아래 코드는하지만 파이썬 3.x를 파이썬 2.6에서 작동

는 :어떻게 파이썬 3에서 file.write()를 오버라이드합니까?

old_file_write = file.write 

class file(): 
    def write(self, d): 
     if isinstance(d, types.bytes): 
      self.buffer.write(d) 
     else: 
      old_file_write(d) 

# ... some code I cannot change or do not want to change 
f = open("x") 
f.write("...") 
f.write(b"...") 
sys.stdout.write(b"...") 
sys.stdout.write("...") 
print(b"...") 
print("...") 

문제는 그 파이썬은 오류가 생성됩니다 첫 번째 줄을 3.X에서 :

NameError: name 'file' is not defined 

어떻게을 파이썬 3.x에서이 작업을 수행합니까?

사실, 2 년 후, 저는 여전히 두 버전 (2.5+ 및 3.x)에서 모두 사용할 수있는 솔루션을 찾고 있습니다.

아직도 내가 왜 이것을 찾고 있는지 궁금한 분들을 위해, 파이썬의 새로운 버전을 사용하기 위해 오래된 코드 (다른 코드, 때로는 수정할 수없는 코드)를 만들 수 있습니다.

이것은 당신이 나쁜 코드와 잘 재생 일부 코드 :

+0

"파일"개체 란 무엇입니까? 더 많은 코드를 입력하십시오. –

+0

자세히 설명해주십시오. 'file'은 파일 객체입니까? 'file.write'는 당신이'old_file_write'에 할당 한 함수 객체입니까, 아니면'file'에 무엇인가를 쓰고'old_file_write'에 기록 된 바이트 수를 저장하려고합니까? – JAB

+2

@Sorin Sbarnea : 문자열과 바이트를 혼동하면 문제가 없습니다. 문자열과 바이트를 같은 것으로 취급 할 수는 없습니다. 그들은 같은 것이 아닙니다. 당신이하는 일은 간단한 방식으로 일할 수 없습니다. 문자열은 바이트로 인코딩됩니다. 그것들은 별개의 것입니다. 응용 프로그램이 손상된 경우 올바르게 수정하여 문자열을 디코딩하십시오. - S.Lott 0 초 전 편집 –

답변

0
old_file_write = file.write 

당신은 file 클래스의 클래스 수준의 방법을 사용하고 쓰기 수있는 방법에 대해이야, 내 코드에 대한 없습니다.

old_file_write(d) 

절대로 작동해서는 안됩니다. 나는 아직도 당신이 잘못 복사하고 붙여 넣고 있다고 생각합니다.

나는 당신이 일 수도

old_file_write(self,d) 

을했을 수 있습니다 생각합니다.

당신의 접근 방식이 좋지 않습니다. 이것을 대신 생각해보십시오.

class MyKindOfFile(file): 
    def write(self, d): 
     if isinstance(d, types.bytes): 
      self.buffer.write(d) 
     else: 
      super(MyFindOfFile, write)(d) 

간단한 상속을보다 일반적인 방식으로 사용하므로 더 잘 작동합니다.

+0

전체적인 생각은 file.write() 파이썬 함수를 'byte'를 허용하는 광산으로 바꾸고 싶다는 것입니다. 질문에 사용 예제를 추가했습니다. – sorin

3

두 가지 문제점이 있습니다.

1 : file 클래스가 특정 클래스에서 상속되지 않습니다. 상황을 올바르게 해석했다면 io.TextIOWrapper의 하위 클래스 여야합니다.

2 : 파이썬 2.6과 3.x 모두에서 types 모듈 (처음에 가져와야 할 모듈)은 bytes 요소가 없습니다. 권장되는 방법은 bytes을 단독으로 사용하는 것입니다.

재실행 조각 :

import io, sys 

class file(io.TextIOWrapper): 
    def write(self, d, encoding=sys.getdefaultencoding()): 
     if isinstance(d, bytes): 
      d = d.decode(encoding) 
     super().write(d) 

old_stdout = sys.stdout # In case you want to switch back to it again 

sys.stdout = file(open(output_file_path, 'w').detach()) # You could also use 'a', 'a+', 'w+', 'r+', etc. 

이 지금은 사용자가 지정한 출력 파일에 sys.stdout.write을 사용하여, 당신이 원하는 일을해야한다. (당신이 디스크의 파일에 기록 할 대신하지 않으려면 아마 일하는 것이 sys.stdout = file(sys.stdout.detach())를 사용하여 기본 sys.stdout 버퍼에 기록합니다.)

는 점에 유의 마십시오, 파이썬 3.x를이 file이 없기 때문에 클래스에는 2.6이 있지만 io 모듈을 사용하는 경우 io 모듈의 클래스 중 하나를 사용해야합니다. 위의 코드는 단지 예일뿐입니다. 더 유연 해지기를 원한다면, 스스로 해결해야 할 것입니다.즉, 작성중인 파일의 종류/작성중인 모드에 따라 io에서 다른 클래스를 사용하는 것이 좋습니다.

+0

예제를 업데이트했습니다.이 예제는 sys.stdout.write에서는 작동하지 않지만 인쇄에서는 작동합니다. – sorin

+0

'sys.stdout.write'를 오버라이드하고 싶습니까? – JAB

+0

사실 필자는 모든 file.write (sys.stdout.write는 단지 동일한 file.write라고 가정)를 덮어 쓰고 싶습니다. – sorin

0

file 객체는 바이트를 기록 할 수 있지만 당신은 당신이 먼저 인코딩하는 데 필요한 디스크 문자열을 작성하려면 올바른 모드

fp = open('file.bin', 'wb') # open in binary mode 
fp.write(b"some bytes") 
pf.close() 

에서 파일 을 열어야합니다.

+0

str과 바이트의 차이를 완전히 이해하고 있지만 str (유니 코드)과 바이트를 모두 파일에 쓰고 싶을 수도 있다는 것을 알아야합니다. 그 주된 이유는 코드를 읽기 쉽도록 유지하는 것인데, 향상된 "write()는 str을 올바르게 인코딩하는 방법을 알게 될 것입니다. – sorin

관련 문제