Pyhton学習ノート10:IOプログラミング

59128 ワード

文書ディレクトリ
  • 1. ファイル読み書き
  • 1.1ファイルを読む
  • 1.2 file-like Object
  • 1.3バイナリファイル
  • 1.4文字符号化
  • 1.5書き込みファイル
  • 2. StringIOとBytesiO
  • 2.1 StringIO
  • 2.2 BytesIO

  • 3. 操作ファイルとディレクトリ
  • 3.1環境変数
  • 3.2操作ファイルとディレクトリ
  • 4. シーケンス化
  • 4.1 JSON
  • 4.2 JSON進級
  • 4.3 EX



  • カテゴリ:同期IOと非同期IOの違い:IO実行の結果を待つかどうか.ただし、非同期の複雑さは同期よりはるかに高い.本章は同期IO
    1.ファイルの読み書き
    ファイルの読み書きステップ:オペレーティングシステムにファイルオブジェクト(ファイル記述子)を開くように要求し、オペレーティングシステムが提供するインタフェースを通じてこのファイルオブジェクトからデータを読み取るか、このファイルオブジェクトにデータを書き込む.
    1.1ファイルを読む
    >>> f = open('E:/4_Programe/1_Python/3_Code/1_LiaoDaDa/test.txt', 'r')   #              ,'r'   
    
    >>> f = open('E:/4_Programe/1_Python/3_Code/1_LiaoDaDa/test.txt', 'r')
    Traceback (most recent call last):
      File "E:\1_Install_Total\8_Anaconda\lib\site-packages\IPython\core\interactiveshell.py", line 2961, in run_code
        exec(code_obj, self.user_global_ns, self.user_ns)
      File "", line 1, in <module>
        f = open('E:/4_Programe/1_Python/3_Code/1_LiaoDaDa/test.txt', 'r')
    FileNotFoundError: [Errno 2] No such file or directory: 'E:/4_Programe/1_Python/3_Code/1_LiaoDaDa/test.txt'   #       ,open()        IOError   ,       
    
    >>> f.read()   #      ,  read()              ,    str    ; 
    'Hello, World!'   
    >>> f.close()   #            
    
  • ファイルの読み書き時にIOErrorが発生する可能性があるため、エラーが発生するとf.close()を呼び出すことができないため、エラーの有無にかかわらずファイルを正しく閉じることができることを保証するためにtry...finallyを使用して実現することができる:
  • try:
        f = open('/path/to/file', 'r')
        print(f.read())
    finally:
        if f:
            f.close()
    
  • しかし、毎回このように書くのは面倒なので、Pythonはwith文を導入して自動的に呼び出してくれましたclose()方法:
  • with open('/path/to/file', 'r') as f:
    	print(f.read())
    
  • 呼び出し方式:
  • with open('E:/4_Programe/1_Python/3_Code/1_LiaoDaDa/test.txt', 'r') as f:
    	print(f.read())   #            ,      ,     
    	print(f.read(size))   #       size      
        
        print(f.readline())   #         ,      size
    
        print(f.readlines())   #              list
        #     
        ['Hello,World!
    '
    , '2
    '
    , '3
    '
    , '4'] for line in f.readlines(): print(line.strip()) # ‘
  • ファイルが小さい場合read()一度に読むのが一番便利です.ファイルサイズが特定できない場合は、read(size)を繰り返し呼び出して保険を比較します.プロファイルの場合は、readlines()を呼び出すのが最も便利です.

  • 1.2 file-like Object
  • 関数が返すようなopen()メソッドのあるオブジェクトは、Pythonではfile-like Objectと総称され、fileのほかにメモリのバイトストリーム、ネットワークストリーム、カスタムストリームなどであってもよい.file-like Objectは特定のクラスから継承する必要はありません.read()メソッドを書けばいいです.
  • read()は、メモリに作成されたfile-like Objectで、一時バッファとしてよく使用されます.

  • 1.3バイナリファイル
  • 先に述べたのはUTF-8符号化されたテキストファイルを読み出し、StringIOモードオープンバイナリファイル
  • >>> f = open('E:/4_Programe/1_Python/3_Code/1_LiaoDaDa/test.png', 'rb')
    >>> f.read()
    b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' #          
    

    1.4文字コード
    #    UTF-8       , open()    encoding()  
    >>> f = open('E:/4_Programe/1_Python/3_Code/1_LiaoDaDa/test1.txt', 'r', encoding='gbk')
    >>> f.read()
    '  '
    
    #            ,     UnicodeDecodeError,  ,    errors  ,               ,           :
    >>> f = open('E:/4_Programe/1_Python/3_Code/1_LiaoDaDa/test1.txt', 'r', encoding='gbk', errors='ignore')
    

    1.5ファイルの書き込み
    >>> f = open('E:/4_Programe/1_Python/3_Code/1_LiaoDaDa/test1.txt', 'w')   # 'w'            ,            ;
    >>> f.write('222')   
    >>> 3
    >>> f.close()
    
    #   with    :
    with open('E:/4_Programe/1_Python/3_Code/1_LiaoDaDa/test1.txt', 'w') as f:
        f.write('Hello, world!')
    
  • 're':読み
  • 'r':書き込み
  • 'w':追加
  • 'a'(読み書き可能、ファイルが存在しなければエラー(IOError)
  • 'r+' == r+w(読み書き可能、ファイルが存在しない場合は作成)
  • 'w+' == w+r(追加書き込み可能、ファイルが存在しなければ作成)
  • 対応する、バイナリファイルであれば、いずれもbを付けておけば良い:'a+' ==a+r'rb''wb''ab''rb+''wb+''ab+'
  • 2.StringIOとBytesiO
    2.1 StringIO
  • その名の通りメモリにstrを読み書き
  • #  str  StringIO,       StringIO,            :
    >>> from io import StringIO
    >>> f = StringIO()
    >>> f.write('hello')
    5
    >>> f.write(' ')
    0
    >>> f.write('world!')
    6
    >>> print(f.getvalue())   # getvalue()          str
    hello world!
    
    #   StringIO。    str   StringIO,          :
    from io import StringIO
    f = StringIO('Hello!
    Hi
    Goodbye!'
    ) while True: s = f.readline() if s == '': break print(s.strip()) Hello! Hi! Goodbye!

    2.2 BytesIO
  • StringIO操作はstrのみで、バイナリデータを操作するにはBytesiO
  • を使用する必要があります.
    # BytesIO         bytes:
    >>> from io import BytesIO
    >>> f = BytesIO() #     BytesIO
    >>> f.write('  '.encode('utf-8'))  #     bytes(     str,    UTF-8   bytes)
    6
    >>> print(f.getvalue())
    b'\xe4\xb8\xad\xe6\x96\x87'
    
    >>> from io import BytesIO
    >>> f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
    >>> f.read()
    b'\xe4\xb8\xad\xe6\x96\x87'
    

    3.操作ファイルとディレクトリ
  • pythonでディレクトリとファイルの操作を実行し、内蔵osモジュールを使用してオペレーティングシステムのインタフェース関数を直接呼び出すことができます:
  • >>> import os
    >>> os.name  #       
    'nt' # Windows  ,  'posix',  Linux,Unix Mac OS X
    
    >>> os.uname()  # uname()   Windows    
    posix.uname_result(sysname='Darwin', nodename='MichaelMacPro.local', release='14.3.0', version='Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64', machine='x86_64')
    

    3.1環境変数
    #              ,     os.environ     ,      
    >>> import os
    >>> os.environ
    environ({
         'ALLUSERSPROFILE': 'C:\\ProgramData', 'AMDRMSDKPATH': 'C:\\Program Files\\AMD\\RyzenMasterSDK\\', 'APPDATA': 'C:\\Users\\Jack\\AppData\\Roaming', 'COMMONPROGRAMFILES': 'C:\\Program Files\\Common Files', 'COMMONPROGRAMFILES(X86)': 'C:\\Program Files (x86)\\Common Files', 'COMMONPROGRAMW6432': 'C:\\Program Files\\Common Files', 'COMPUTERNAME': 'DESKTOP-3VRSQ0V', 'COMSPEC': 'C:\\Windows\\system32\\cmd.exe', 'CONDA_DEFAULT_ENV': 'base', 'CONDA_EXE': 'C:\\Anaconda\\Scripts\\conda.exe', 'CONDA_PREFIX': 'C:\\Anaconda', 'CONDA_PROMPT_MODIFIER': '(base) ', 'CONDA_PYTHON_EXE': 'C:\\Anaconda\\python.exe', 'CONDA_SHLVL': '1', 'DRIVERDATA': 'C:\\Windows\\System32\\Drivers\\DriverData', 'HOMEDRIVE': 'C:', 'HOMEPATH': '\\Users\\Jack', 'LOCALAPPDATA': 'C:\\Users\\Jack\\AppData\\Local', 'LOGONSERVER': '\\\\DESKTOP-3VRSQ0V', 'NUMBER_OF_PROCESSORS': '12', 'ONEDRIVE': 'C:\\Users\\Jack\\OneDrive', 'OS': 'Windows_NT', 'PATH': 'C:\\Anaconda;C:\\Anaconda\\Library\\mingw-w64\\bin;C:\\Anaconda\\Library\\usr\\bin;C:\\Anaconda\\Library\\bin;C:\\Anaconda\\Scripts;C:\\Anaconda\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\Program Files\\Intel\\WiFi\\bin\\;C:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;D:\\01 Installation path\\17 MATLAB\\runtime\\win64;D:\\01 Installation path\\17 MATLAB\\bin;C:\\Anaconda;C:\\Anaconda\\Library\\mingw-w64\\bin;C:\\Anaconda\\Library\\usr\\bin;C:\\Anaconda\\Library\\bin;C:\\Anaconda\\Scripts;C:\\Users\\Jack\\AppData\\Local\\Microsoft\\WindowsApps;D:\\01 Installation path\\07 Bandizip\\;C:\\PyCharm\\PyCharm 2018.3.3\\bin', 'PATHEXT': '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', 'PROCESSOR_ARCHITECTURE': 'AMD64', 'PROCESSOR_IDENTIFIER': 'AMD64 Family 23 Model 8 Stepping 2, AuthenticAMD', 'PROCESSOR_LEVEL': '23', 'PROCESSOR_REVISION': '0802', 'PROGRAMDATA': 'C:\\ProgramData', 'PROGRAMFILES': 'C:\\Program Files', 'PROGRAMFILES(X86)': 'C:\\Program Files (x86)', 'PROGRAMW6432': 'C:\\Program Files', 'PROMPT': '(base) $P$G', 'PSMODULEPATH': 'C:\\Program Files\\WindowsPowerShell\\Modules;C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules;C:\\Program Files\\Intel\\Wired Networking\\', 'PUBLIC': 'C:\\Users\\Public', 'PYCHARM': 'C:\\PyCharm\\PyCharm 2018.3.3\\bin;', 'PYTHONIOENCODING': '936', 'SYSTEMDRIVE': 'C:', 'SYSTEMROOT': 'C:\\Windows', 'TEMP': 'C:\\Users\\Jack\\AppData\\Local\\Temp', 'TMP': 'C:\\Users\\Jack\\AppData\\Local\\Temp', 'USERDOMAIN': 'DESKTOP-3VRSQ0V', 'USERDOMAIN_ROAMINGPROFILE': 'DESKTOP-3VRSQ0V', 'USERNAME': 'Jack', 'USERPROFILE': 'C:\\Users\\Jack', 'WINDIR': 'C:\\Windows'})
    
    #             ,    os.environ.get('key'):
    >>> os.environ.get('PATH')
    'C:\\Anaconda;C:\\Anaconda\\Library\\mingw-w64\\bin;C:\\Anaconda\\Library\\usr\\bin;C:\\Anaconda\\Library\\bin;C:\\Anaconda\\Scripts;C:\\Anaconda\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\Program Files\\Intel\\WiFi\\bin\\;C:\\Program Files\\Common Files\\Intel\\WirelessCommon\\;D:\\01 Installation path\\17 MATLAB\\runtime\\win64;D:\\01 Installation path\\17 MATLAB\\bin;C:\\Anaconda;C:\\Anaconda\\Library\\mingw-w64\\bin;C:\\Anaconda\\Library\\usr\\bin;C:\\Anaconda\\Library\\bin;C:\\Anaconda\\Scripts;C:\\Users\\Jack\\AppData\\Local\\Microsoft\\WindowsApps;D:\\01 Installation path\\07 Bandizip\\;C:\\PyCharm\\PyCharm 2018.3.3\\bin'
    >>> os.environ.get('x', 'default')
    'default'
    

    3.2操作ファイルとディレクトリ
  • 操作ファイルとディレクトリの関数の一部はosモジュールに、一部はos.pathモジュールに、注意してください
  • #            :
    >>> os.path.abspath('.')
    'C:\\Windows\\system32'
    #              ,               :
    >>> os.path.join('C:\\Windows\\system32', 'testdir')
    'C:\\Windows\\system32\\testdir'
    #         :
    >>> os.mkdir('C:\\Windows\\system32\\testdir')
    #       :
    >>> os.rmdir('C:\\Windows\\system32\\testdir')
    
  • os.path.join()関数によって2つのパスを1つに合成する:
  • part-1/part-2  #  linux/unix/mac ,           ;
    
    part-1\part-2  #  windows         ;
    
  • パスをos.path.split()関数で分割
  • >>> os.path.split('C:\\Windows\\system32\\testdir\\file.txt')
    ('C:\\Windows\\system32\\testdir', 'file.txt')   #                  
    
    >>> os.path.splitext('/path/to/file.txt')   #               
    ('/path/to/file', '.txt')
    #   ,              ,          
    
  • ファイル操作では、現在のディレクトリの下にtest.txtファイルがあると仮定します.
  • #       :
    >>> os.rename('test.txt', 'test.py')
    #     :
    >>> os.remove('test.py')
    
  • ファイルをコピーする関数はosモジュールには存在せず、shutilモジュールのcopyfile()関数によってファイルをコピーすることができる.
  • pythonの特性を利用してファイルをフィルタする:
  • #             :
    >>> [x for x in os.listdir('.') if os.path.isdir(x)]
    ['0409', 'AdvancedInstallers', 'am-et', 'AppLocker', 'appraiser', 'AppV', 'ar-SA', 'bg-BG', 'Boot', 'Bthprops', 'CatRoot', 'catroot2', 'CodeIntegrity',...]
    >>> [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
    ['apis.py', 'config.py', 'models.py', 'pymonitor.py', 'test_db.py', 'urls.py', 'wsgiapp.py']
    
    

    4.シーケンス化
  • プログラムの実行中、すべての変数はメモリの中で、例えばdictを定義して、私达はいつでも変数を修正することができて、例えばnameBillに修正して、しかしプログラムが终わると、変数の占有するメモリはオペレーティングシステムにすべて回収されて、もし修正したBillをディスクの上で保存していないならば、次回プログラムを再実行して、変数はまたBob
  • に初期化される.
    d = dict(name='Bob', age=20, score=88)
    
  • 変数をメモリから格納または転送可能にするプロセスをシーケンス化、pythonでpicklingと呼び、シーケンス化後、シーケンス化されたコンテンツをディスクに書き込むか、ネットワークを介して別のマシンに転送することができ、逆に、変数コンテンツをシーケンス化されたオブジェクトからメモリに読み直すことを逆シーケンス化、すなわちunpicklingと呼ぶ.
  • pythonは、pickleモジュールを提供し、シーケンス化を実現します:
  • #         :
    >>> import pickle
    >>> d = dict(name='Bob', age=20, score=88)
    >>> pickle.dumps(d)  #                 bytes
    b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x03\x00\x00\x00Bobq\x02X\x03\x00\x00\x00ageq\x03K\x14X\x05\x00\x00\x00scoreq\x04KXu.'
    
    #             file-like Object:
    >>> f = open('dump.txt', 'wb')
    >>> pickle.dump(d, f)
    >>> f.close()
    
    #           :
    >>> import pickle
    >>> f = open('dump.txt', 'rb')
    >>> d = pickle.load(f)   #        file-like Object          
    >>> f.close
    <built-in method close of _io.BufferedReader object at 0x0000024248596E08>
    >>> d
    {
         'name': 'Bob', 'age': 20, 'score': 88}
    #                  ,           
    
  • pickleの問題は、他のプログラミング言語特有のシーケンス化の問題と同様に、pythonにのみ使用でき、異なるバージョン間のpythonは互換性がありません.

  • 4.1 JSON
  • 異なるプログラミング言語間でオブジェクトを伝達するには、オブジェクトを標準フォーマットにシーケンス化しなければならない.JSONは文字列であり、すべての言語で読み取ることができると同時に、Webページで読み取ることができ、非常に便利である.
  • JSON表示の対象は標準的なJavaScript言語の対象であり、python内蔵のjsonモジュールは非常に完璧なpythonオブジェクトをJSONに提供している.
  • # dumps()      str,       JSON,   dump()       JSON    file-like Object
    >>> import json
    >>> d = dict(name='Bob', age='20', score=88)
    >>> json.dumps(d)
    '{"name": "Bob", "age": "20", "score": 88}'
    
    #   , JSON     python  , loads()     load()  ,   JSON        ,   file-like Object           
    >>> json_str='{"age": 20, "score": 88, "name": "Bob"}'
    >>> json.loads(json_str)
    {
         'age': 20, 'score': 88, 'name': 'Bob'}
    

    4.2 JSON進級
  • pythonのdictオブジェクトはJSONの{}に直接シーケンス化できます.では、classで表されるオブジェクトをどのようにシーケンス化しますか.例えば、定義されたStudentクラス:
  • import json
    
    class Student(object):
        def __init__(self, name, age, score):
            self.name = name
            self.age = age
            self.score = score
    
    s = Student('Bob', 20, 88)
    print(json.dumps(s))
    
    #      ,       :
    Traceback (most recent call last):
      ...
    TypeError: Object of type Student is not JSON serializable
    
  • エラーの原因はStudentオブジェクトがシーケンス化可能なJSONオブジェクトではないことですが、これは合理的ではありません.dumps()メソッドのパラメータリストをよく見ると、最初に必要なobjパラメータのほか、dumpsメソッドにはオプションパラメータがたくさん用意されています.https://docs.python.org/3/library/json.html#json.dumpsこれらのオプションパラメータにより、JSONシーケンス化をカスタマイズできます.前のコードでStudentクラスインスタンスをJSONにシーケンス化できないのは、デフォルトではdumpsメソッドがSdudentインスタンスをJSONの{}オブジェクトにする方法が分からないからです.
  • オプションパラメータdefaultは、任意のオブジェクトをJSONにシーケンス化可能なオブジェクトにすることです.
    def student2dict(std):
    	return {
         
    		'name': std.name,
    		'age': std.age,
    		'score': std.score
    	}
    
  • このようにSdudentインスタンスは、まずStudent関数によってStudent2dict()に変換され、その後、JSON:
  • に順次シーケンス化される.
    >>> print(json. dumps(s, default=student2dict))
    {
         "age": 20, "name": "Bob", "score": 88}
    
  • ただし、次回dictクラスのインスタンスに遭遇した場合は、JSONにシーケンス化できません.私たちは怠け者を盗んで、任意のTeacherの例をclass:
  • に変えることができます.
    print(json. dumps(s, default=lambda obj: obj.__dict__))
    
  • 通常dictのインスタンスにはclassの属性があるため、彼は__dict__であり、インスタンス変数を格納するために使用され、dictを定義したclassなどの少数の例外もある.
  • 同様に、JSONを1つの__slots__オブジェクトインスタンスに逆シーケンス化する場合、Studentメソッドはまず1つのloads()オブジェクトを変換し、その後、私たちが入力したdict関数はobject_hookdictインスタンスに変換する責任を負います:Studentインスタンス:
  • def dict2student(d):
    	return Student(d['name'], d['age'], d['score'])
    
    >>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
    >>> print(json.loads(json_str, object_hook = dict2student))
    <__main__.Student object at 0x10cd3c190>
    
  • は、逆シーケンス化Studentインスタンスオブジェクトを印刷します.

  • 4.3 EX
    中国語に対してJSONシーケンス化を行う場合、json.dumps()ensure_asciiパラメータを提供し、このパラメータが結果に与える影響を観察する.
    import json
    
    obj = dict(name = '  ', age = 20)
    s = json.dumps(obj, ensure_ascii = True)
    print(s)
    
    #     
    {
         "name": "\u5c0f\u660e", "age": 20}