Search code examples
windowsunicodepython-2.xpopen

running a cmd file with an accented character in its name, in Python 2 on Windows


I have the file t2ű.cmd on Windows with an accented character in its name, and I'd like to run it from Python 2 code.

Opening the file (open(u't2\u0170.cmd')) works if I pass the filename as a unicode literal, but no str literal works, because \u0170 is not on the code page of Windows. (See this question for more on opening files with accented characters in their name: opening a file with an accented character in its name, in Python 2 on Windows.)

Running the file from the Command Prompt without Python works.

I tried passing an str literal to os.system, os.popen, os.spawnl and subprocess.call (both with and without the shell), but it wasn't able to find the file.

These don't work, they raise UnicodeDecodeError: 'ascii' codec can't encode character u'\u170'...:

  • os.system(u't2\u170.cmd')
  • os.popen(u't2\u170.cmd')
  • os.spawnl(u't2\u170.cmd', u't2')
  • subprocess.call(u't2\u170.cmd')
  • subprocess.call(u'"t2\u170.cmd"')
  • subprocess.call([u't2\u170.cmd'])

In this project it's not feasible to upgrade to Python 3.

It's not feasible to rename the file, because these files can have arbitrary (user-supplied) names on a read-only share, and also the directory name can contain accented characters.

In C I would use any of the wsystem, wpopen or wspawnl functions in <process.h>.

Preferably I'm looking for a solution which works with the standard Python modules (no need to install packages). But I'm interested in any solution.

I need a solution which doesn't open a new window.

Eventually I want to pass command-line arguments to program, and the arguments will contain arbitrary Unicode characters.


Solution

  • This is based on the comment by @eryksun.

    We need to call the system call CreateProcessW or the C functions wspawnl, wsystem or wpopen. Python 2 doesn't have anything built in which would call any of these functions. Writing an extension module in C or calling the functions using ctypes could be a solution.

    The C functions CreateProcessA, spawnl, system and popen don't work.