2016-08-19 5 views
3

WindowsでのPython 3.5.2の魔法のバグは、私の一日を殺しました。下記のファイルは、このシステムに障害が発生した:コーデックヘッダー付きのASCII安全ファイルでのエンコードの問題(行数に応じて)

C:\Python35\python.exe encoding-problem-cp1252.py 
File "encoding-problem-cp1252.py", line 2 
SyntaxError: encoding problem: cp1252 

はほとんど何も入っていません - 離れてcodingヘッダから空行の束があるが、任意の行は、空であっても、それが削除されたとき再び働く。私はそれがローカルの問題だと思ったので、同じ動作を示した0​​をセットアップしました。

Pythonでは何が起こっていますか?

以下のファイルのbinary accurate versionがあります:

#!/usr/bin/env python 
# -*- coding: cp1252 -*- 


""" 
There is nothing in this file, except that it is more 
than 50 lines long. Running it with Python 3.5.2 on 
Windows gives the following error: 

    >python encoding-problem-cp1252.py 
     File "encoding-problem-cp1252.py", line 2 
    SyntaxError: encoding problem: cp1252 

    >python 
    Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit (Intel)] on win32 
    Type "help", "copyright", "credits" or "license" for more information. 

If you remove any lines from this file, it will 
execute successfully. 
""" 



def restore(dump): 
    """ 













    """ 
    return 



def main(): 
    print('ok') 



if __name__ == '__main__': 
    main() 
+1

Windowsでは実行されていませんが、これはデバッグは困難です。ファイルはMac OS XとLinux上で正常に動作します。あなたがバグを見つけたように思えます。http://bugs.python.org/でファイルを提出してください。 –

+1

[関連ソースコード](https://hg.python.org/cpython/file/v3.5.2/Parser)を見てください。 /tokenizer.c#l510)CRLFの処理に疑問があります。ファイルをUnixの行末(現在のように)からWindowsの行末まで変換するとどうなりますか?ファイルが長すぎると、バッファリングに関する問題が発生する可能性があります。 –

+0

誰かが私のためにこのバグを埋めることができますか?私はこのトラッカーから、数年前にリストにあまりにも感情的な反応があるのを禁止されています。 –

答えて

3

これはissue #20731によって引き起こさ回帰のように見えます。

fd = fileno(tok->fp); 
/* Due to buffering the file offset for fd can be different from the file 
* position of tok->fp. If tok->fp was opened in text mode on Windows, 
* its file position counts CRLF as one char and can't be directly mapped 
* to the file offset for fd. Instead we step back one byte and read to 
* the end of line.*/ 
pos = ftell(tok->fp); 
if (pos == -1 || 
    lseek(fd, (off_t)(pos > 0 ? pos - 1 : pos), SEEK_SET) == (off_t)-1) { 
    PyErr_SetFromErrnoWithFilename(PyExc_OSError, NULL); 
    goto cleanup; 
} 

問題は、Windowsを使用するために、あなたのファイルを変換するとき消える(:位置計算が間違っにつながることbeing calculated hereオフセット、あなたのファイルのみLF文字を持っている間、常にCRLF改行コードがあるだろうと仮定しているように見えますCRLF)行の終わりですが、実際のソリューションではないクロスプラットフォームのスクリプトでは理解できます。

私はissue #27797を提出しました。これはPython自体で修正する必要があります。

+0

問題は 'ftell(tok-> fp)'が-1を返すことです。バグを引き起こすために必要な改行の数は、シバンの長さとコーディング仕様によって決まります。ファイル位置を計算するために、 'ftell'は、バッファ内の未読バイト数を実際のOSファイル位置から減算します。問題は、バッファ内の行末がすでにLFに変換されていることですが、OSファイルの位置は変換されていない行末に基づいています。したがって、 'ftell'は、ファイルがCRLF行末を使用していると仮定し、未読LFあたり2バイトを減算します。適切な条件で-1を返します。これはエラーのようです。 – eryksun

+0

他にもありますか? ;-)ところで、私は 'ftell'を-1に戻すこれらの特殊なケースだけを見ました。また、-1より小さい位置を返すこともできます。この場合、 'lseek'呼び出しは' SEEK_SET'のため失敗します。 – eryksun

+0

@eryksun:おっと!分析をしていただきありがとうございます! –